2017-10-11 90 views
0

我需要將像素數組寫入磁盤,並在相同的應用程序中讀取該文件。出於某種原因,這些文件在應用程序終止之前不會寫入磁盤。 (只有它們纔會出現在他們保存的目錄中)。我在IntelliJ IDEA中編寫這個應用程序,如果這對於知道任何有用的信息。如何在應用程序終止前將圖像保存到磁盤?

如何確保文件立即寫入磁盤?這是我的代碼:

protected void savePixelstoPNG(int[] pixels, String fileName) { 
    BufferedImage image = new BufferedImage(getMapWidth(), getMapHeight(), BufferedImage.TYPE_INT_RGB); 
    Graphics graphics = image.getGraphics(); 

    for(int y = 0; y < getMapHeight(); y++) { 
     for(int x = 0; x < getMapWidth(); x++) { 
      graphics.setColor(new Color(pixels[x + y * getMapWidth()])); 
      graphics.fillRect(x, y, 1, 1); 
     } 
    } 

    try { 
     File file = new File(fileName); 
     ImageIO.write(image, "PNG", file); 
    } catch(IOException e) { 
     e.printStackTrace(); 
    } 
} 

編輯:我檢查了文件夾,他們實際上正在寫入磁盤。但是,這些更改不會反映到項目目錄中(文件保存到Java包中),直到應用程序終止。因此,當我在讀取這些文件後(在相同的應用程序生命週期內)讀取這些文件時,應用程序無法找到這些文件,即使它們存在於磁盤上。

編輯2:這裏是我用來從類路徑使用相對目錄路徑讀取文件的代碼。初始資源從類路徑中讀取。當它們被更新,它們將被寫入不同的目錄中的類路徑使原來的資源不會被覆蓋,因爲原來的資源都應該給每個應用程序重新運行時最初讀:

void myLoadMethod() { 
     loadMapTiles("resource/tilemap_1-1.png"); 
     loadTriggerTiles("resource/triggermap_1-1.png"); 
} 


protected void loadMapTiles(@NotNull String path) { 
     URL url = getClass().getClassLoader().getResource(path); 
     loadTiles(url, mapTiles); 
} 

protected void loadTriggerTiles(@NotNull String path) { 
     URL url = getClaass().getClassLoader().getResource(path); 
     loadTiles(url, triggerTiles); 
} 

protected void loadTiles(@NotNull URL url, @Nullable int[] dest) { 
     try { 
      System.out.println("Trying to load: " + url.toString() + "..."); 
      BufferedImage map = ImageIO.read(url); 
      int[] pixels = new int[mapWidth * mapHeight]; 
      map.getRGB(0, 0, mapWidth, mapHeight, pixels, 0, mapWidth); 
      System.arraycopy(pixels, 0, dest, 0, dest.length); 
      System.out.println("Success!"); 
     } catch (IOException e) { 
      System.out.println("failed..."); 
      e.printStackTrace(); 
     } 
    } 
} 

注意mapTilestriggerTiles是包含在類中的字段loadMapTilesloadTriggerTilesloadTiles

+0

據我所知,但到'#的ImageIO的write'靜態調用這是否自動 – DayTripperID

+0

你如何嘗試在讀?你認爲文件是在課程路徑上,還是從外部?因爲「文件被保存到一個java包」可能是你寫入(源)目錄,但嘗試從類路徑讀取,並且只有在IntelliJ開始新的運行時,它們纔會被複制到類路徑中。 – cello

+0

是的!我正在使用通過相對目錄實例化的URL從classpath讀取數據。我寫了絕對目錄,因爲我無法弄清楚如何寫入相對目錄。我無法讓它識別一個相對目錄(保持找不到目錄)所以我想我需要弄清楚如何將它寫入相對目錄? – DayTripperID

回答

1

您應區分源文件和類路徑。

源通常駐留在某種src目錄中。例如。對於Maven項目的標準是src/main/java*.java文件和src/main/resources其他資源*.properties

但後來的Java文件進行編譯和*.class文件拷貝到一些輸出目錄。例如。對於Maven這是target/...,許多其他工具具有binoutput作爲編譯的類文件夾。資源保存在相同的位置。

看起來您正在將文件寫入src並試圖從其他位置讀取它們(例如,Class#getResourceAsStream(path)將從classpath讀取數據)。事實上,您可以讀取下一個應用程序運行的文件,這讓我認爲,在下一個版本中,它會被複制到輸出目錄,並對您的應用程序「可見」。

在你的代碼

URL url = getClass().getClassLoader().getResource(path); 

構造一個URL到文件預計將在類路徑中(最有可能在${projectRoot}/target/classes/${path})。

雖然

File file = new File(fileName); 

創建相對於執行目錄路徑的文件(最有可能相對於${projectRoot})。

通常ClassLoader#getResource(path)應該只用於獲得類路徑上的靜態資源。

對於磁盤上的構建路徑使用Paths#get(path)。如果你絕對需要一個網址,你可以這樣來做:

Paths.get(path).toURI().toURL(); 
+0

我添加了用於在原始問題的EDIT2下讀取文件的代碼。寫代碼包含在原始問題中,所以希望它全部在那裏 – DayTripperID

+0

你應該小心你的相對位置的基礎。你可以使用絕對?或者傳遞基礎目錄作爲參數? –

+0

我絕對沒有問題。然而,我絕對會遇到的問題是,我必須將目錄指定到整個文件系統的根目錄,而不是回到項目根目錄。因此,例如'/ home/user/IdeaProjects/MyProject/src/my_image.png'我必須在某處配置不正確的東西。我正在標記你的答案,因爲你的解釋是有道理的。 – DayTripperID

相關問題