2014-03-31 112 views
0

所以在製作RPG的過程中,我發現製作一個程序可以讓我創建一個地圖並保存而不必編輯一個字節數組的數量。我需要能夠將地圖保存爲文本文件,以便可以在RPG中讀取和重新創建地圖。但我不知道如何寫一個2D字節數組到文件。將2D字節數組寫入文本文件Java

例如:

byte[][] map = new byte[][]{ {0,0,0,0,0}, {1,1,1,0,0} }; 

我想要的文本文件,以便能夠輸出是這樣的:

0 0 0 0 0 
1 1 1 0 0 

我究竟應如何去寫一個二維字節數組的內容一個文本文件?

回答

2

最簡單的方式IMO:

// create your output stream. Use the current running directory for your project 
FileOutputStream fout = new FileOutputStream(new File(System.getProperty("user.dir"), "test.txt")); 
// print it out so you know where it is... maybe? 
System.out.println(new File(System.getProperty("user.dir"), "test.txt")); 

byte[][] map = new byte[][] { { 0, 0, 0, 0, 0 }, { 1, 1, 1, 0, 0 } }; 
// loop through your map, 2d style 
for (int i = 0; i < map.length; i++) { 
    for (int j = 0; j < map[i].length; j++) { 
     // get the string value of your byte and print it out 
     fout.write(String.valueOf(map[i][j]).getBytes()); 
    } 
    // write out a new line. For different systems the character changes 
    fout.write(System.getProperty("line.separator").getBytes()); 
} 
// close the output stream 
fout.close(); 
+0

謝謝!你的想法是最簡單的,只需很少的調整! – user3140916

0

製作一個嵌套for循環。

例如:

for(int i = 0; i < array.length; i++) { // first dimension (x) 
    for(int v = 0; v < array2.length; v++) { // second dimension (y) 
     array[i][v].... 
    } 
} 
0
final PrintWriter writer = new PrintWriter("your-file-name.txt", "UTF-8"); 
final StringBuilder arrayContent = new StringBuilder(); 

for(byte outer[] : map) { 
    for(byte inner : outer) { 
     arrayContent.append(inner); 
    } 
    arrayContent.append("\n"); 
} 
writer.write(arrayContent.toString()); 
writer.close(); 

你必須處理來自PrintWriter的例外情況爲好,但如果你想扔或趕上他們在你的方法它依賴。

1

你可以使用一個ObjectOutputStream包裝一FileOutputStream寫你的二維數組到文件,然後使用一個ObjectInputStream包裝一FileInputStream閱讀它回。 注意:這不會給你一個純文本文件,你可以通過手動打開它來閱讀和修改,如果這是你需要的,那麼這是不適合你的。

下面是如何做到這一點的例子:

import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 

public class Serialization { 
    public static void main(String[] args) { 
     byte[][] toSerialize = new byte[][] {{0,0,0,0,0}, {1,1,1,0,0}}; 
     byte[][] readArray; 

     try { 
      ObjectOutputStream oos = new ObjectOutputStream(
       new FileOutputStream("my_file.dat")); 
      oos.writeObject(toSerialize); 
      oos.close(); 

      ObjectInputStream ois = new ObjectInputStream(
       new FileInputStream("my_file.dat")); 
      readArray = (byte[][]) ois.readObject(); 

      for (int i = 0; i < readArray.length; i++) { 
       for (int j = 0; j < readArray[i].length; j++) { 
        System.out.print(readArray[i][j] + " "); 
       } 
       System.out.println(); 
      } 
      ois.close(); 
     } catch (Exception e) {} 
    } 
} 

在實踐中,你要分開進行讀取和寫入單獨的方法,可能save()load()。我也強烈建議你不要catch (Exception e)像我一樣。

您也不妨考慮使用種子生成地圖並存儲,而不是寫整個地圖文件,然而執行該完全是另一回事。

1

這是不檢查可能發生的任何錯誤的情況非常樂觀的實現。這只是一個使用字節數組而不是文件的例子。但它應該像使用文件輸入和輸出流替換字節數組流時一樣工作。通過檢查格式不正確的文件格式使其更加強大。

這個想法是在每行的前面加上它的長度,然後是行的字節。您的地圖具有統一的列大小,因此您可以將每列的長度保存一次。只需按照自己的喜好調整即可。好玩:

public static void main(String[] args) throws Exception { 
    byte[][] dungeon = new byte[][] { 
     {0,0,0,0,0}, 
     {1,1,1,0,0} 
    }; 
    ByteArrayOutputStream os = new ByteArrayOutputStream(); 
    saveMap(os, dungeon); 
    ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray()); 
    byte[][] maze = loadMap(in); 
} 

private static void saveMap(OutputStream saveStream, byte[][] dungeon) throws Exception { 
    try (BufferedOutputStream os = new BufferedOutputStream(saveStream)) { 
     for (int row=0; row<dungeon.length; row++) { 
      os.write(toBytes(dungeon[row].length)); 
      os.write(dungeon[row]); 
     } 
    } 
} 

private static byte[][] loadMap(InputStream saveStream) throws Exception { 
    List<byte[]> rows = new ArrayList<>(); 
    try (BufferedInputStream in = new BufferedInputStream(saveStream)) { 
     while (in.available() != 0) { 
      byte[] column = new byte[toInt(in.read(), in.read())]; 
      for (int idx = 0; idx < column.length; idx++) { 
       column[idx] = (byte) in.read(); 
      } 
      rows.add(column); 
     } 
    } 
    return rows.toArray(new byte[rows.size()][]); 
} 

private static byte[] toBytes(int value) { 
    return new byte[] { (byte) (value >>> 8), (byte) value }; 
} 

private static int toInt(int high, int low) { 
    return (high << 8) | (0x00FF & low); 
} 
2

你可以有一個MappedByteBuffer一去,它的設計是高效/快IO操作:

//Bytes 
    byte[][] map = new byte[][]{ {0,0,0,0,0}, {1,1,1,0,0} }; 

    //Path to Desktop in this case 
    Path pathway = Paths.get(System.getProperty("user.home")).resolve("Desktop").resolve("MyNewFile.txt"); 

    //Get size of file we will need, this is the size of each array (5 bytes) * num of arrays 
    // + line separator space * number of arrays as is one for each line separation 
    int size = ((map[0].length * map.length)) + System.lineSeparator().getBytes().length * map.length; 

    //Random access file for MappedByteBuffer. Put in try() for autoclose 
     try(RandomAccessFile raf = new RandomAccessFile(pathway.toFile(), "rw")){ 
      //MappedByteBuffer for speed 
      MappedByteBuffer mBuff = raf.getChannel().map(MapMode.READ_WRITE, 0, size); 
      for(int i = 0; i < map.length; i++) { 
       for(int j = 0; j < map[i].length; j++) { 
        mBuff.put(String.valueOf(map[i][j]).getBytes()); //Write value 
       } 
       mBuff.put(System.lineSeparator().getBytes()); //Write line break 
      } 
    } catch (IOException io) { 
     System.out.println("IO Error: " + io.getMessage()); 
    } 
+0

我以前沒見過自動關閉。 +1教我新的東西! – JonK

+0

@JonK No-Problem = D它被稱爲一個嘗試與資源塊。如果某些東西實現了AutoCloseable接口,它可以放在括號中,並在最後使用AutoClose。它認爲它意味着在關閉一些代碼混亂的情況下保存IO異常。 – Levenal

+0

也可能保存在'finally'塊中。現在只要我們在工作中使用Java 7 ... – JonK