如何最有效地将文件(从 Java 读取)传递给本机方法?

发布于 2024-08-30 11:32:48 字数 639 浏览 1 评论 0原文

我有大约。我想将 30000 个文件(每个 1MB)放入本机方法中,该方法只需要一个字节数组及其大小作为参数。

我查看了一些示例和基准(例如 http://nadeausoftware.com/articles/2008/02 /java_tip_how_read_files_quickly),但它们都做了一些其他奇特的事情。

基本上我不关心文件的内容,我不想访问该文件或字节数组中的某些内容或对其执行任何其他操作。我只想将文件放入本地方法中,该方法尽可能快地接受字节数组。

目前我正在使用 RandomAccessFile,但是速度非常慢(10MB/s)。

有什么类似的东西

byte[] readTheWholeFile(File file){ ... }

我可以放入

native void fancyCMethod(readTheWholeFile(myFile), myFile.length())

“你会建议什么”中吗?

I have approx. 30000 files (1MB each) which I want to put into a native method, which requires just an byte array and the size of it as arguments.

I looked through some examples and benchmarks (like http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly) but all of them do some other fancy things.

Basically I don't care about the contents of the file, I don't want to access something in that file or the byte array or do anything else with it. I just want to put a file into a native method which accepts an byte array as fast as possible.

At the moment I'm using RandomAccessFile, but that's horribly slow (10MB/s).

Is there anything like

byte[] readTheWholeFile(File file){ ... }

which I could put into

native void fancyCMethod(readTheWholeFile(myFile), myFile.length())

What would you suggest?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

回忆躺在深渊里 2024-09-06 11:32:48

使用常规数组可能效率较低,因为 VM 在将数组传递给本机代码时可能会复制该数组,并且还可能在 I/O 期间使用中间内存。

要获得最快的 IO,请使用 ByteBuffer.allocateDirect 分配字节缓冲区。底层数组是“特殊的”,因为它不是常规 JVM 堆的一部分。本机代码和 I/O 可以直接访问数组。

要将数据读入缓冲区,请使用,

ByteBuffer byteBuffer = ByteBuffer.allocateDirect(randomAccessFile.length());
RandomAccessFile.getChannel().read(byteBuffer, 0);

将后备数组传递给 JNI 使用

byte[] byteArray = byteBuffer.array();

然后,您可以将此数组和文件长度传递给 JNI。

创建直接缓冲区确实很繁重,由于所有文件都是 1MB(或左右),您应该能够在多个文件上重用相同的缓冲区。

希望这有帮助!

Using regular arrays may be inefficient, as the VM may copy the array when passing it to native code, and may also use intermediate memory during I/O.

For the fastest IO, use ByteBuffer.allocateDirect to allocate a byte buffer. The underlying array is "special" in that it is not part of the regular JVM heap. Native code and I/O can access the array directly.

To read data into the buffer use,

ByteBuffer byteBuffer = ByteBuffer.allocateDirect(randomAccessFile.length());
RandomAccessFile.getChannel().read(byteBuffer, 0);

To get the backing array to pass to JNI use

byte[] byteArray = byteBuffer.array();

You can then pass this array and the file length to JNI.

The direct buffers are realtively heavy to create, As all your files are 1MB (or thereabouts) you should be able to reuse the same buffer on multiple files.

Hope this helps!

从此见与不见 2024-09-06 11:32:48

我不完全确定这就是您所要求的,但听起来您想将文件的内容作为字节数组有效地传递给本机方法。

如果是这种情况,我建议您使用 BufferedInputStream 读取 Java 中的文件内容,并将它们存储在通过 ByteBuffer#allocateDirect ,这样就可以传到JNI端,整体访问了。现在,在本机方法中,您可以调用 GetDirectByteBufferAddress 直接访问缓冲区。

I'm not entirely sure this is what you're asking but it sounds like you want to efficiently pass the contents of a file as a byte array to a native method.

If that's the case, I suggest you read the file contents in Java using a BufferedInputStream and store them in a ByteBuffer that was allocated via ByteBuffer#allocateDirect, this way it can be passed to the JNI side and accessed in whole. Now, in the native method, you can call GetDirectByteBufferAddress to access the buffer directly.

农村范ル 2024-09-06 11:32:48

这是您可以实现的 readFileFully 示例

   public static byte[] readFileFully(String aFileName) throws IOException
   {
      byte[] retData = null;

      File inputFile = new File(aFileName);
      if (inputFile == null || !inputFile.exists() || !inputFile.canRead())
      {
         throw new IOException("INVALID FILE : " + aFileName);
      }

      // Read in the file data
      BufferedInputStream iStream = null;
      try
      {
         iStream = new BufferedInputStream(new FileInputStream(inputFile));
         int size = (int)inputFile.length();
         retData = new byte[size];
         int bytes_read = 0;

         // read stuff in here
         while (bytes_read < size)
         {
            bytes_read += iStream.read(retData,bytes_read,size - bytes_read);
         }
      }
      finally
      {
         if (iStream != null)
         {
            try
            {
               iStream.close();
            }
            catch(IOException e)
            {
            }
         }
         inputFile = null;
      }
      return retData;
   }

Here is a sample of readFileFully that you could implement

   public static byte[] readFileFully(String aFileName) throws IOException
   {
      byte[] retData = null;

      File inputFile = new File(aFileName);
      if (inputFile == null || !inputFile.exists() || !inputFile.canRead())
      {
         throw new IOException("INVALID FILE : " + aFileName);
      }

      // Read in the file data
      BufferedInputStream iStream = null;
      try
      {
         iStream = new BufferedInputStream(new FileInputStream(inputFile));
         int size = (int)inputFile.length();
         retData = new byte[size];
         int bytes_read = 0;

         // read stuff in here
         while (bytes_read < size)
         {
            bytes_read += iStream.read(retData,bytes_read,size - bytes_read);
         }
      }
      finally
      {
         if (iStream != null)
         {
            try
            {
               iStream.close();
            }
            catch(IOException e)
            {
            }
         }
         inputFile = null;
      }
      return retData;
   }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文