在Java中创建和读取自定义文件类型

在Java中创建和读取自定义文件类型,java,Java,我正在创建一个安装程序,其中有一些资源文件(.xmls、.zip文件、一个.jar文件等)必须在安装过程中读取,但我想将它们打包到一个自定义文件(即.dat文件)中,这样在分发时,用户就不会对它们进行太多的处理。问题是安装程序必须用Java编写,我以前从未用任何编程语言做过这种事情。有可能吗?如果是这样的话,我如何以一种可以被我的Java应用程序读取的方式打包它,以及如何让我的Java应用程序读取它?扩展名通常与文件的解释方式关系不大 如果您希望只使用config.dat而不是config.xm

我正在创建一个安装程序,其中有一些资源文件(.xmls、.zip文件、一个.jar文件等)必须在安装过程中读取,但我想将它们打包到一个自定义文件(即.dat文件)中,这样在分发时,用户就不会对它们进行太多的处理。问题是安装程序必须用Java编写,我以前从未用任何编程语言做过这种事情。有可能吗?如果是这样的话,我如何以一种可以被我的Java应用程序读取的方式打包它,以及如何让我的Java应用程序读取它?

扩展名通常与文件的解释方式关系不大

如果您希望只使用
config.dat
而不是
config.xml
,只需重命名文件即可。(您通常会给xml解析器一个
InputStream
Reader
作为输入,它可以读取任何文件,而不考虑扩展名)

如果您描述的问题是将多个文件(.zip、.jar等)合并到一个.dat文件中,您可以将它们压缩在一起,并使用.dat扩展名命名zip文件。Java对zip文件有很好的支持,并且无论文件名/扩展名如何,都可以处理zip文件

  • 相关链接:

在Java(或其他任何语言)中创建/读取文件时,文件扩展名并不严格地与文件数据的实际结构相匹配。如果我愿意,我可以制作一个XML文件
file.gweebz
。操作系统和应用程序不知道如何使用它,但一旦打开,就可以清楚地知道它是XML

也就是说,遵循已经建立的约定通常是好的,通常
。dat
文件是二进制格式的文件。您可以根据需要使用.dat,但请注意,某些用户可能具有文件类型的OS绑定,单击您的文件可能会在其系统上导致不同于预期的行为

至于如何在Java中实现它。在Java中获取文件句柄很容易

File myFile = new File("/dir/file.gweebz");

它就这么简单,你可以随意命名。您将需要其他类来写入和读取文件或进行压缩,但我假设您知道如何进行压缩。如果没有,本网站将有答案。

关于此文件类型的要求,您需要自己回答许多问题。它需要压缩吗?加密的?它是否需要支持随机访问读取,或者流读取是否足够好

我可能错了,但我不认为这就是你在这个问题上要问的。如果我读对了,我想你是在问“如何读取和写入任意文件数据?”

这就是我要回答的问题。更新你的问题,如果这不是你想要的

自定义文件类型可以使用DataInputStream和DataOutputStream类轻松实现。这些将允许您在流中读写原语(boolean、char、byte、int、long、float、double)。还有一些读写UTF-8编码字符串、字节数组和其他一些好东西的方便方法

让我们开始吧

为了便于讨论,让我们假设我的所有数据元素都是字节数组。他们每个人都有一个名字。因此,我的文件类型可以逻辑地建模为
映射
。我将实现自定义文件类型读写器类,如下所示:

public class MyFileTypeCodec {

   public static void writeToFile(File f, Map<String, byte[]> map)
      throws IOException {

      // Create an output stream
      DataOutputStream stream = new DataOutputStream(
         new BufferedOutputStream(new FileOutputStream(f))
      );

      // Delegate writing to the stream to a separate method
      writeToStream(stream, map);

      // Always be sure to flush & close the stream.
      stream.flush();
      stream.close();
   }

   public static Map<String, byte[]> readFromFile(File f)
      throws IOException {

      // Create an input stream
      DataInputStream stream = new DataInputStream(
         new BufferedInputStream(new FileInputStream(f))
      );

      // Delegate reading from the stream to a separate method
      Map<String, byte[]> map = readFromStream(stream);

      // Always be sure to close the stream.
      stream.close();

      return map;
}

   public static void writeToStream(DataOutputStream stream, Map<String, byte[]> map)
      throws IOException {

      // First, write the number of entries in the map.
      stream.writeInt(map.size());

      // Next, iterate through all the entries in the map
      for (Map.Entry<String, byte[]> entry : map.entrySet()) {

         // Write the name of this piece of data.
         stream.writeUTF(entry.getKey());

         // Write the data represented by this name, making sure to
         // prefix the data with an integer representing its length.
         byte[] data = entry.getValue();
         stream.writeInt(data.length);
         stream.write(data);
      }

   }

   public static Map<String, byte[]> readFromStream(DataInputStream stream)
      throws IOException {

      // Create the data structure to contain the data from my custom file
      Map<String, byte[]> map = new HashMap<String, byte[]>();

      // Read the number of entries in this file
      int entryCount = stream.readInt();

      // Iterate through all the entries in the file, and add them to the map
      for (int i = 0; i < entryCount; i++) {

         // Read the name of this entry
         String name = stream.readUTF();

         // Read the data associated with this name, remembering that the
         // data has an integer prefix representing the array length.
         int dataLength = stream.readInt();
         byte[] data = new byte[dataLength];
         stream.read(data, 0, dataLength);

         // Add this entry to the map
         map.put(name, data);
      }

      return map;

   }

}
公共类MyFileTypeCodec{
公共静态void writeToFile(文件f,映射)
抛出IOException{
//创建一个输出流
DataOutputStream=新的DataOutputStream(
新BufferedOutputStream(新文件输出流(f))
);
//将对流的写入委托给单独的方法
writeToStream(流、映射);
//始终确保冲洗并关闭水流。
stream.flush();
stream.close();
}
公共静态映射readFromFile(文件f)
抛出IOException{
//创建一个输入流
DataInputStream=新的DataInputStream(
新的BufferedInputStream(新的FileInputStream(f))
);
//将从流的读取委托给单独的方法
Map Map=readFromStream(stream);
//始终确保关闭该流。
stream.close();
返回图;
}
公共静态void writeToStream(DataOutputStream、Map)
抛出IOException{
//首先,在地图上写下条目数。
stream.writeInt(map.size());
//接下来,遍历映射中的所有条目
对于(Map.Entry:Map.entrySet()){
//写下这段数据的名称。
stream.writeUTF(entry.getKey());
//写入此名称表示的数据,确保
//使用表示数据长度的整数作为数据的前缀。
字节[]数据=entry.getValue();
stream.writeInt(data.length);
流写入(数据);
}
}
公共静态映射readFromStream(DataInputStream)
抛出IOException{
//创建数据结构以包含自定义文件中的数据
Map Map=newhashmap();
//读取此文件中的条目数
int entryCount=stream.readInt();
//遍历文件中的所有条目,并将它们添加到映射中
for(int i=0;i
基本思想是,如果可以将任何数据表示为原语的某种组合,则可以将其写入输出流(并再次读取)。数组(或其他集合)可以