如何在Java动态Web服务应用程序中写入本地文件?

huangapple go评论55阅读模式
英文:

How to write to a local file in a Java Dynamic WebService application?

问题

以下是我翻译好的内容:

/**
 * 用于读取存储在 JSON 文件中数据的实用方法。
 * 
 * @param filePath 所需数据库表的路径
 * @return 所需表的内容
 * @throws IOException 在找不到所需文件时抛出
 */
public static String readFile(String filePath) throws IOException {
    InputStream inputStream = DBHelper.class.getResourceAsStream(filePath);
    String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
    return content;
}

/**
 * 将新书添加到 Books.json 文件中
 */
public void postBook(Book book, String filePath) {
    
    // 创建带有漂亮打印的 Gson 实例
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    
    // 首先,将 Book 对象转换为 Json 字符串
    try {
       
        File file = new File(filePath);
        OutputStream out = new FileOutputStream(file);
        
        // 此逻辑将检查文件是否存在。如果在指定位置找不到文件,它会创建一个新文件
        if (!file.exists()) {
            file.createNewFile();
        }
        
        List<Book> books;
        String updatedBooksJson;
        
        // 如果文件为空,只需将对象放入其中 - 不需要先前的逗号
        if (DBHelper.tableIsEmpty(filePath)) {
            books = new ArrayList<Book>();
            books.add(book);
            
            updatedBooksJson = gson.toJson(books);
            
            // 写入文件
            byte[] bytes = updatedBooksJson.getBytes();
            out.write(bytes[6]);
            out.flush();
            
        } else {
            // 文件不为空。读取当前文件中的产品列表,将其转换为 List<Book>,添加新的 Book,然后更新文件
            
            books = getAllBooks(filePath);
            
            // 将新书添加到现有书籍列表中:
            books.add(book);
            
            // 将更新后的书籍列表写入 Books.json 文件
            updatedBooksJson = gson.toJson(books);
            
            // 清空旧文件内容
            FileChannel.open(Paths.get(filePath), StandardOpenOption.WRITE).truncate(0).close();
            
            // 写入新的文件内容
            byte[] bytes = updatedBooksJson.getBytes();
            out.write(bytes[6]);
            out.flush();
        }
        
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

这是写入 /com/ebook/database/Books.json 文件时发生 FileNotFoundException 的问题。

英文:

I have a file that contains json data Books.json. The file is located in package com.ebook.database. I can successfully read the file's contents, but I when I try to write to the file, I get a FileNotFoundException.

Below is my project's strudture, showing the package in which the Books.json file is located:
如何在Java动态Web服务应用程序中写入本地文件?

Below is the code I use to successfully read the file's contents (filePath receives a String value of /com/ebook/database/Books.json and reads the file just fine:

/**
	 * A utility method for reading the data stored in a json file.
	 * 
	 * @param filePath path to the desired database table 
	 * @return the contents of the desired table
	 * @throws IOException occurs when the desired file is not found
	 */
	public static String readFile(String filePath) throws IOException {
		InputStream inputStream = DBHelper.class.getResourceAsStream(filePath);
		String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
        return content;
	}

Below is the code I'm using to try to access the same Books.json file for writing, unsuccessfully:

/**
	 * Adds a new Book to the Books.json file
	 * */
	public void postBook(Book book, String filePath) {
		
		//create Gson instance with pretty-print
	    Gson gson = new GsonBuilder().setPrettyPrinting().create();
	    
		//First, convert the Product object into a Json string
		try {
			   
			File file = new File(filePath);
			OutputStream out = new FileOutputStream(file);
			
			/* This logic will check whether the file
			   * exists or not. If the file is not found
			   * at the specified location it would create
			   * a new file*/
			  if (!file.exists()) {
			     file.createNewFile();
			  }
			
			   List&lt;Book&gt; books;
			   String updatedBooksJson;
			   
			   //if file is empty, just throw the object in -- no prior comma needed.	   
			   if(DBHelper.tableIsEmpty(filePath)) {
				   books = new ArrayList&lt;Book&gt;();
				   books.add(book);
				   
				   updatedBooksJson = gson.toJson(books);
				   
				   //writing to the file.
				   byte[] bytes = updatedBooksJson.getBytes();
				   out.write(bytes[6]);
				   out.flush();
				    
			   } else {
				   //The file is not empty.  Read the list of Products currently
				   //in the file, convert to List&lt;Product&gt;, add the new Product, and
				   //update the file
				   
				   books = getAllBooks(filePath);
				   
				   //add the new product to the existing list of products:
				   books.add(book);
				   
				   //write the updated products list to the Products.json file
				   updatedBooksJson = gson.toJson(books);
				   
				   //clear the old file contents
				   FileChannel.open(Paths.get(filePath), StandardOpenOption.WRITE).truncate(0).close();
				      
				   //write the new file contents
				 //writing to the file.
				   byte[] bytes = updatedBooksJson.getBytes();
				   out.write(bytes[6]);
				   out.flush();
			   }
			   
			   out.close();
			} catch (IOException e) {
				e.printStackTrace();
			  }
	}

Below is the resulting stacktrace when attempting to write to the /com/ebook/database/Books.json file:

INFO: Server startup in 2782 ms
java.io.FileNotFoundException: \com\ebook\database\Books.json (The system cannot find the path specified)
	at java.base/java.io.FileOutputStream.open0(Native Method)
	at java.base/java.io.FileOutputStream.open(FileOutputStream.java:292)
	at java.base/java.io.FileOutputStream.&lt;init&gt;(FileOutputStream.java:235)
	at java.base/java.io.FileOutputStream.&lt;init&gt;(FileOutputStream.java:185)
	at com.ebook.dal.BookDAO.postBook(BookDAO.java:59)
	at com.ebook.services.BookService.addNewBook(BookService.java:38)
	at com.ebook.resources.BookResource.postNewBook(BookResource.java:72)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:124)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:167)
	at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:219)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:79)
	at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:469)
	at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:391)
	at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:80)
	at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:253)
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
	at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
	at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:232)
	at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680)
	at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:392)
	at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:365)
	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:318)
	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:165)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:1025)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:452)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1201)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:654)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:317)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.base/java.lang.Thread.run(Thread.java:835)
Oct 11, 2020 3:32:40 PM org.apache.catalina.core.StandardContext reload

答案1

得分: 0

你在这里混合使用了类路径和本地文件系统路径。在不清楚自己在做什么的情况下,不应该尝试这样覆盖类路径中的元素,因为这可能会在重新启动应用程序时引起行为异常。只需将其放在文件系统的某个位置,并始终在那里进行读写操作。

英文:

You are mixing classpath and local file system paths here. You should never try to overwrite elements in the classpath like that without knowing what you're doing as that would potentially charge the behavior of the app when you restart it. Just put the somewhere on the file system and consistently read and write there.

huangapple
  • 本文由 发表于 2020年10月12日 04:35:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/64308760.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定