2017-10-11 10 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(); 
    } 
} 

EDIT : 나는 실제로 디스크에 즉시 기록됩니다. 그러나 이러한 변경 사항은 응용 프로그램이 종료 될 때까지 프로젝트 디렉토리 (파일은 Java 패키지에 저장 됨)에 반영되지 않습니다. 따라서 파일을 저장 한 후 동일한 응용 프로그램 수명 내에서 해당 파일을 읽으려고하면 응용 프로그램에서 파일을 찾을 수 없습니다 (디스크에 있더라도).

EDIT 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(); 
     } 
    } 
} 

mapTiles을 그 및 triggerTiles은 보유하는 클래스에 포함 된 필드입니다. loadMapTilesloadTriggerTilesloadTiles

+0

AFAIK하지만'ImageIO에서 번호의 write'에 정적 호출을 자동으로 – DayTripperID

+0

어떻게 당신이 그 (것)들을 읽으려고 않음을 수행합니다 당신이 절대적으로 URL을해야 할 경우 당신은 이런 식으로 할 수 있습니까? 파일이 수업 경로 또는 외부에 있다고 가정합니까? "파일이 자바 패키지에 저장되기 때문에"당신은 (소스) 디렉토리에 쓸 수 있지만 클래스 경로에서 읽으려고 할 수 있으며 일단 IntelliJ에서 새로운 실행을 시작하면 클래스 패스로 복사됩니다. . – cello

+0

예! 상대 경로로 인스턴스화 된 URL을 사용하여 classpath에서 읽는 중입니다. 상대 디렉토리에 쓰는 방법을 알 수 없기 때문에 절대 디렉토리에 썼습니다. 상대 디렉토리를 인식하지 못했습니다. 디렉토리를 찾을 수 없습니다. 그래서 상대 디렉토리에 파일을 쓰는 방법을 알아야합니까? – DayTripperID

답변

1

원본 파일과 클래스 경로를 구분해야합니다.

일반적으로 소스는 일종의 src 디렉토리에 있습니다. 예 : Maven 프로젝트에 대한 표준 등,

다른 자원 *.properties에 대한 *.java 파일 src/main/javasrc/main/resources입니다 그러나 나중에 자바 파일을 컴파일하고 *.class 파일은 일부 출력 디렉터리에 복사됩니다. 예 : Maven의 경우 이것은 target/...이고 다른 많은 도구는 컴파일 된 클래스 폴더로 bin 또는 output입니다. 리소스는 동일한 위치에 저장됩니다.

src에 파일을 쓰고 다른 위치에서 파일을 읽는 것 같습니다 (예 : Class # getResourceAsStream (path)가 클래스 경로에서 데이터를 읽음). 다음 번 앱 실행 파일을 읽을 수 있다는 사실 때문에 다음 빌드에서는 출력 디렉토리에 복사되어 앱에 "보이게"된다고 생각합니다. 코드

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

은 (${projectRoot}/target/classes/${path}에서 대부분의 아마)이이 클래스 경로에있을 것으로 예상된다 파일에 URL을 구축합니다.

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