2017-10-11 15 views
0

Je dois écrire une matrice de pixels sur le disque et lire ce fichier dans la même application. Pour une raison quelconque, les fichiers n'écrivent pas sur le disque tant que l'application n'est pas terminée. (Seulement alors ils apparaissent dans le répertoire dans lequel ils sont sauvegardés). J'écris cette application dans IntelliJ IDEA si cela est utile de le savoir.Comment enregistrer l'image sur le disque avant la fin de l'application?

Comment puis-je m'assurer que le fichier est écrit sur le disque immédiatement? Voici mon code:

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: Je visitai les dossiers et ils sont en fait en cours d'écriture sur le disque immédiatement. Toutefois, ces modifications ne sont pas reflétées dans le répertoire du projet (les fichiers sont enregistrés dans un package Java) jusqu'à ce que l'application se termine. Donc, quand je vais lire ces fichiers après les avoir sauvegardés (dans la même durée de vie de l'application), l'application ne peut pas trouver les fichiers, même s'ils existent sur le disque.

EDIT 2: Voici le code que j'utilise pour lire le fichier à partir du classpath en utilisant un chemin de répertoire relatif. Les ressources initiales sont lues à partir du classpath. Quand ils sont mis à jour, ils sont écrits dans un répertoire différent dans le classpath pour que les ressources d'origine ne sont pas remplacées, car les ressources originales sont censées être lu d'abord chaque fois que l'application est exécutée à nouveau:

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

Notez que mapTiles et triggerTiles sont des champs contenus dans la classe qui détient loadMapTilesloadTriggerTiles et loadTiles

+0

, mais autant que je sache l'appel statique 'ImageIO # write' fait automatiquement – DayTripperID

+0

Comment essayez-vous de les lire? Est-ce que vous supposez que le fichier est sur le chemin de la classe, ou de l'extérieur? Parce que "les fichiers sont sauvegardés dans un paquet java", il se peut que vous écrivez dans le répertoire (source), mais essayez de lire depuis le chemin de classe, et ils ne seront copiés dans le classpath qu'une fois que vous lancez une nouvelle exécution dans IntelliJ . – cello

+0

Oui! Je lis de classpath en utilisant une URL instanciée avec un répertoire relatif. J'ai écrit dans le répertoire absolu parce que je ne pouvais pas comprendre comment écrire dans un répertoire relatif. Je ne pouvais pas le faire reconnaître un répertoire relatif (gardé le répertoire introuvable) Donc je suppose que je dois trouver comment l'écrire dans un répertoire relatif? – DayTripperID

Répondre

1

Vous devez différencier entre les fichiers source et classpath.

Les sources résident généralement dans un répertoire src. Par exemple. pour le projet Maven la norme est src/main/java pour *.java fichiers et src/main/resources pour d'autres ressources *.properties, etc.

Mais les fichiers plus tard Java sont compilés et *.class fichiers sont copiés dans un répertoire de sortie. Par exemple. pour Maven c'est target/..., de nombreux autres outils ont bin ou output en tant que dossiers de classe compilés. Les ressources sont enregistrées au même emplacement.

Il semble que vous écrivez des fichiers à src et que vous essayez de les lire à partir d'un autre emplacement (par exemple, la classe # getResourceAsStream (path) lit les données de classpath). Le fait que vous puissiez lire le fichier suivant lors de l'exécution de l'application me fait penser que sur la prochaine version, il est copié dans le répertoire de sortie et devient "visible" pour votre application.

Sur votre code

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

construit une URL de fichier qui devrait être sur classpath (plus probablement ${projectRoot}/target/classes/${path}).

Alors que

File file = new File(fileName); 

crée un fichier dans le chemin relatif au répertoire d'exécution (très probablement par rapport à ${projectRoot}).

Généralement ClassLoader#getResource(path) doit être utilisé uniquement pour obtenir des ressources statiques sur votre chemin de classe.

Pour créer des chemins sur un disque, utilisez Paths#get(path). Si vous avez absolument besoin d'une URL que vous pouvez le faire de cette façon:

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

J'ai ajouté le code utilisé pour lire le fichier sous EDIT2 de la question initiale. Le code d'écriture est contenu dans la question d'origine, donc j'espère que tout est là – DayTripperID

+0

Vous devriez faire attention à la base de vos emplacements relatifs. Pouvez-vous utiliser absolu? Ou passer le répertoire de base en tant que paramètre? –

+0

Je n'ai aucun problème en utilisant absolu. Cependant, le problème que je rencontre avec absolute est que je dois spécifier le répertoire jusqu'au répertoire racine de tout mon système de fichiers, pas à la racine du projet. Donc, par exemple '/ home/utilisateur/IdeaProjects/MyProject/src/mon_image.png' je dois avoir quelque chose de mal configuré quelque part. Je marque votre réponse cependant parce que votre explication est logique. – DayTripperID