2014-03-31 88 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