什么';在Java中,将非常小的字符串写入文件的最快方法是什么?
我的代码需要取一个介于0和255之间的整数值,并将其作为字符串写入文件。它需要很快,因为它可能会很快地被重复调用,所以在重载情况下,任何优化都会变得明显。这里还有其他一些问题需要解决,即如何高效地将大量数据写入文件,但如何处理少量数据呢 以下是我目前的做法:什么';在Java中,将非常小的字符串写入文件的最快方法是什么?,java,android,performance,file-io,Java,Android,Performance,File Io,我的代码需要取一个介于0和255之间的整数值,并将其作为字符串写入文件。它需要很快,因为它可能会很快地被重复调用,所以在重载情况下,任何优化都会变得明显。这里还有其他一些问题需要解决,即如何高效地将大量数据写入文件,但如何处理少量数据呢 以下是我目前的做法: public static void writeInt(final String filename, final int value) { try { // Convert the int to a stri
public static void writeInt(final String filename, final int value)
{
try
{
// Convert the int to a string representation in a byte array
final String string = Integer.toString(value);
final byte[] bytes = new byte[string.length()];
for (int i = 0; i < string.length(); i++)
{
bytes[i] = (byte)string.charAt(i);
}
// Now write the byte array to file
final FileOutputStream fileOutputStream = new FileOutputStream(filename);
fileOutputStream.write(bytes, 0, bytes.length);
fileOutputStream.close();
}
catch (IOException exception)
{
// Error handling here
}
}
publicstaticvoidwriteint(最终字符串文件名,最终int值)
{
尝试
{
//将int转换为字节数组中的字符串表示形式
最终字符串=整数.toString(值);
最终字节[]字节=新字节[string.length()];
对于(int i=0;i
我不认为
BufferedOutputStream
在这里会有帮助:构建缓冲区刷新的开销可能会对3字符写入产生反作用,不是吗?我还可以做其他改进吗?在我看来,您无法加快速度。如果没有其他改进,BufferedOutputStream在这里将毫无帮助。如果我们看一下src,我们会看到FileOutputStream.write(字节b[],int off,int len)直接将字节数组发送到本机方法,而BufferedOutputStream.write(字节b[],int off,int len)是同步的,首先将数组复制到它的缓冲区,在关闭时它会将字节从缓冲区刷新到实际流
除此之外,本例中最慢的部分是打开/关闭文件。谷歌快速搜索带来了不同大小文件的不同写/读操作基准:
作者得出的结论是,
WinFileIO.writeblock
将数据写入文件的速度最快,尽管I/O操作严重依赖于多种因素,如操作系统文件缓存、文件索引、磁盘碎片、,文件系统缓存等。我认为,在满足0-255范围要求的情况下,这是最有效的。使用缓冲写入器效率较低,因为它会创建一些临时结构,而您不需要在写入这么少字节的情况下创建这些临时结构
static byte[][] cache = new byte[256][];
public static void writeInt(final String filename, final int value)
{
// time will be spent on integer to string conversion, so cache that
byte[] bytesToWrite = cache[value];
if (bytesToWrite == null) {
bytesToWrite = cache[value] = String.valueOf(value).getBytes();
}
FileOutputStream fileOutputStream = null;
try {
// Now write the byte array to file
fileOutputStream = new FileOutputStream(filename);
fileOutputStream.write(bytesToWrite);
fileOutputStream.close();
} catch (IOException exception) {
// Error handling here
} finally {
if (fileOutputStream != null) {
fileOutputStream.close()
}
}
}
我认为,这里的瓶颈是IO,这两个改进可能会有所帮助:
- 考虑更新的粒度。也就是说,如果你的应用每秒不需要超过20次更新,那么你可以优化你的应用,使其每1/20秒写入不超过1次更新。这可能是非常有益的,取决于环境
- Java NIO已被证明对于较大的大小要快得多,因此对较小的大小进行实验也是有意义的,例如,将
写入
,而不是通道
输入流
- 很抱歉来参加聚会这么晚:)
我认为试图优化代码可能不是正确的方法。如果重复写入同一个小文件,并且每次都必须写入,而不是在应用程序中缓冲,那么到目前为止,最大的考虑因素将是文件系统和存储硬件
关键是,如果你每次都在使用硬件,那么你会严重破坏它。但是,如果您的系统正在缓存写操作,那么您可能可以让它根本不经常命中硬件:数据在到达硬件之前已经被覆盖,并且只会写入新数据
但这取决于两件事。首先,当您的文件系统在写入旧文件之前先写入新文件时,它会做什么?有些文件系统最终可能会在日志中写入额外的条目,甚至在一个位置写入旧文件,然后在另一个物理位置写入新文件。那将是一个杀手
另一方面,当要求覆盖某些内容时,您的硬件会做什么?如果是传统硬盘,它可能只会覆盖旧数据。如果它是闪存(如果这是安卓系统的话,它很可能会是这样),磨损将逐渐变平,并且它将继续写入驱动器的不同位
在磁盘缓存和文件系统方面,您确实需要尽一切可能确保在将缓存推送到磁盘之前发送1000个更新,只写入最后一个更新
由于这是安卓系统,您可能会看到ext2/3/4。仔细查看日志记录选项,并调查ext4中延迟分配的影响。也许最好的选择是使用ext4,但是关闭日志记录。如果您确实需要在每次写入后主动刷新,那么在代码中所做的任何事情都不会对您有所帮助。缓冲区的存在是有原因的。每次调用该方法时,是否限制您创建和写入新文件?如果没有,您可以保留一个相当大的字节[]作为缓冲区,并且只在程序退出或缓冲区已满时写入文件。谢谢大家。该文件将始终存在,但每次写入时我都需要完全替换其内容。作为一名长期的Android开发人员,我很好奇您的用例定义为“重负载”,因为移动设备上的“重负载”通常不是一件好事,因为它会破坏电池寿命,并将您的设备变成一块真正的热砖块。啊,很公平。继续。:)这是针对Android上的Java,而不是C#。除非我遗漏了什么。对不起,这是一个Java问题,不是C。我现在把它添加到标题中,因为在标签中很容易漏掉它。:)@马特:不,是我错过了一些东西。毕竟,Java和C#都是经过管理的、垃圾收集的、带有框架的高级编程语言(或者在案例o中是VM)