随机生成10亿个整数,写入文件。下面是代码:FileWriter f=new FileWriter("D:/data.txt");
BufferedWriter buf=new BufferedWriter(f,1024*512);
int o=0;
while(o<10000){
int []array=new int[100000];
for(int i=0;i<array.length;i++)
array[i]=(int) (Math.random()*1000000);
int j=0;
while(j<array.length){
buf.write(String.valueOf(array[j]));
System.out.println(array[j]);
j++;
}
o++;
}
buf.close();发现速度真的是太慢了,该怎么优化一下使写入文件的速度加快,各位大牛指点Javaio大数据

解决方案 »

  1.   

    你看这代码是不是写入文件的次数太多了导致用的时间太多了  估计要用几个小时才能写完10亿个整数
    1个整数4bit,10亿个就是4G,我这个文件就得是4G 
      

  2.   

    你这个占地方可不止4G哦,一般的簇大小都是4KB,所以就算你只有1bit内容都是要占4KB硬盘空间滴
      

  3.   


    public static void main(String[] args) throws Exception { long startTime = System.currentTimeMillis();

    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c:/test.txt")); Random rad = new Random(); long i = 0;
    while (i < 1000000000) {
    bos.write(int2bytes(rad.nextInt()));
    i++;
    } bos.flush();
    bos.close(); System.out.println(System.currentTimeMillis() - startTime); } static byte[] int2bytes(int i) throws IOException {
    //System.out.println(i); int len = 0;// 数字长度
    int index = 10;// 游标
    boolean isNegative = false;// 是否负数
    byte[] buff = new byte[11];// int最大长度为10位,包括符号11位 if (i < 0) {
    i = 0 - i;
    len++;
    isNegative = true;
    } while (i != 0) {
    buff[index--] = (byte) ((i % 10 + 48) & 0xff);
    i /= 10;
    len++;
    } if (isNegative) {
    buff[index] = 45 & 0xff;
    } byte[] rs = new byte[len]; System.arraycopy(buff, 11 - len, rs, 0, len); return rs;
    }耗时103548ms,生成的文件有9.29G,硬盘写入速度倒成瓶颈了
      

  4.   

    第二次耗时131072ms平均写入速度90m/s左右,目前一般的机械硬盘也就这性能了。String.valueOf每次都会拆箱装箱int然后new一个String出来,写入的时候String还会转换成byte[]数组。所以直接把这部分自己写了个方法来做,直接把int转成byte[]省掉了创建对象的开销。
      

  5.   

    刚测了下,不写入硬盘只生成并转换成byte要耗时50s左右,这个应该就跟cpu计算速度有关了
      

  6.   

    亲啊,java 的int占4个字节,直接">>"转成4个字节不行吗? 
    System.arraycopy()这个底层的内存拷贝也很耗时的。
        /** 
         * int转byte数组 
         *  
         * @param a 
         * @return 
         */  
        public static byte[] int2Byte(int a) {  
            byte[] b = new byte[4];  
            b[0] = (byte) (a >> 24);  
            b[1] = (byte) (a >> 16);  
            b[2] = (byte) (a >> 8);  
            b[3] = (byte) (a);  
      
            return b;  
        }  
      

  7.   

    C底层IO采用缓存读写,512字节/次的写 会不会快点?
      

  8.   

    我直接将生成0-100万之间的整数写入txt文件,用下面代码
    long startTime = System.currentTimeMillis();
    FileWriter f=new FileWriter("D:/data.txt");
    BufferedWriter buf=new BufferedWriter(f,1024*512);
    int o=0;
    while(o<1000000000){
    buf.write((int) (Math.random()*1000000));
    o++;
    }
    buf.close();
    System.out.println(System.currentTimeMillis() - startTime);
    文件只有1.26G 耗时305016   这是什么原因啊,是不是数据没有完全写完呢?
      

  9.   

    怎么实现的 512/次字节的写BufferedWriter buf=new BufferedWriter(f,1024*512);这样是把缓存区设定大小为500M ,缓存区满了才写入了文件吗?
      

  10.   


    亲,字符串可跟int直接转成的4个字节不同哦,而且我刚开始也是你那样想的,后来试了一下发现生成的文本文档根本打不开,一堆乱码。
    现在硬盘的簇大小一般是4k用4k应该好点吧
    另外楼主是想把数字一字符串的形式写入文本文档还是用字节的形式存储这些数字额?
      

  11.   


    static void t8(){
    byte[] buff = new byte[512];//4*128//128个int
    Random rand = new Random(System.currentTimeMillis());
    rand.nextBytes(buff);
    OutputStream out = null;

    try{
    out = new FileOutputStream("c:\\test1.data");

    long l = System.currentTimeMillis();
    for(int i=0,end=10000*10000*10; i<end; i+=128){
    out.write(buff, 0, 512);
    out.flush();
    }
    System.out.println(System.currentTimeMillis()-l);
    out.close();
    }catch(Exception ex){
    ex.printStackTrace();
    }
    }这个测试结果:
    写入:3.72 GB (4,000,002,048 字节)
    耗时:125734我估计 我机器上java 写硬盘速度就这样了。
      

  12.   

    lz的慢 应该是慢在cpu运算及内存copy上。
      

  13.   

    用字符串存储好像就不会乱码了,我是想写入文件,然后再取出来对他们排序,用字节存储也是可以的。只是取出来的时候要排序,还是要转换成int形式。
      

  14.   

    1 你这个array数组是否有必要?2 是否一定要txt,也就是打开来看,如果只有一个数字1234,就要能肉眼看到是1234?换句话说,可以用字节流替代字符流。同样一个数字123456789,字符流9个字符,至少要9个字节(看编码格式,可能18个字节)。而字节流的话,只要是int范围内,无论多大,最多只要4个字节。如果只是想要存储,数字肉眼看不看得懂无所谓(其实那么大量的数字,看不看得懂没区别),可以:    final int n = 100;
        final int max = 1000000000;    File file = new File("D:/data.dat");
        DataOutputStream dos = null;
        try {
          dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(
              file)));
          for (int i = 0; i < n; i++) {
            int x = (int) (Math.random() * max);
            System.out.println(x);
            dos.writeInt(x);
          }
        } finally {
          if (dos != null) {
            try {
              dos.close();
              dos = null;
            } catch (Exception ex) {
            }
          }
        }
        System.out.println("==========以下为读取===========");
        DataInputStream dis = null;
        try {
          dis = new DataInputStream(new BufferedInputStream(new FileInputStream(
              file)));
          for (int i = 0; i < n; i++) {
            int x = dis.readInt();
            System.out.println(x);
          }
        } finally {
          if (dis != null) {
            try {
              dis.close();
              dis = null;
            } catch (Exception ex) {
            }
          }
        }
      

  15.   

    public static void main(String[] args) throws Exception { long startTime = System.currentTimeMillis(); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c:/test.dat")); Random rad = new Random(); long i = 0;
    while (i < 1000000000) {
    bos.write(int2bytes(rad.nextInt()));
    i++;
    } bos.flush();
    bos.close(); System.out.println(System.currentTimeMillis() - startTime); } static int bytes2int(byte[] b) {
    return b[0] << 24 + b[1] << 16 + b[2] << 8 + b[3];
    } static byte[] int2bytes(int i) {
    byte[] rs = new byte[4]; rs[0] = (byte) (i >> 24);
    rs[1] = (byte) (i >> 16);
    rs[2] = (byte) (i >> 8);
    rs[3] = (byte) (i); return rs;
    }
    耗时69217ms,文件大小3.72 GB (4,000,000,000 字节),占用空间3.72 GB (4,000,002,048 字节),不写硬盘耗时11419ms。
      

  16.   

    如果确保数字很小,即使内存这边用int,读写这里可以改成read/writeShort,更节省空间目前int读写,n=1000000000,稳定在4,000,000,000 字节(约3.72G)相对于你字符格式的版本,估计可以省去一半,运行才100多秒。
    如果是lz的n=100000,不到50毫秒,大小才390K
    小绵羊,没必要发明轮子,直接用DataI/OStream即可。
      

  17.   

    虽然你的代码更进一步了,但是还是有bug
      

  18.   

        byte[] bytes = int2bytes(-1234);
        int x = bytes2int(bytes);
        System.out.println(x);>>>
      

  19.   


    cpu运算慢意思是指我的电脑问题吗,这样生成的是字节数据,如果以字节的形式存储,我的初衷是想把写到文件的整数进行排序,那是不是可以重新把这些字节组成一个个整数再进行排序
      

  20.   

    意思是 你为了达到同样的目地 消耗了更多的cpu资源
      

  21.   

    如果文件最大限制在2G以内,我这有个速度更快一点的。
    超过2G的文件,RandomAccessFile 就不支持了。这个应该和底层实现有关吧。
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.channels.FileChannel.MapMode;
    import java.util.Random;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.CyclicBarrier;
    public class Test_3 {
    static Block POISON = new Block();
    static class Block{
    static enum State{init,writing,finished};
    State stat=State.init;
    int index;
    int[] rand;
    }
    static class RandomThread extends Thread{
    CyclicBarrier barrier;
    BlockingQueue<Block> randomQueue;
    BlockingQueue<Block> writerQueue;
    int max;
    public RandomThread(CyclicBarrier barrier,
    BlockingQueue<Block> randomQueue,
    BlockingQueue<Block> writerQueue,
    int max) {
    super();
    this.barrier = barrier;
    this.randomQueue = randomQueue;
    this.writerQueue = writerQueue;
    this.max = max;
    } public void run(){
    Block block = null;
    Random rand = new Random(System.currentTimeMillis());
    try {
    while((block=randomQueue.take())!=POISON){
    for(int i=0;i<block.rand.length;i++){
    block.rand[i] = rand.nextInt(max);
    }
    writerQueue.put(block);
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    } finally{
    try {
    barrier.await();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    }
    static class WriterThread extends Thread{
    BlockingQueue<Block> writerQueue;
    FileChannel channel;
    CyclicBarrier barrier;
    public WriterThread(BlockingQueue<Block> writerQueue,
    FileChannel channel, CyclicBarrier barrier ) {
    super();
    this.writerQueue = writerQueue;
    this.channel = channel;
    this.barrier = barrier;
    }
    public void run(){
    Block block = null;
    try {
    while((block=writerQueue.take())!=POISON){
    MappedByteBuffer buffer = channel.map(MapMode.READ_WRITE, block.index<<2, block.rand.length<<2);
    for(int i=0;i<block.rand.length;i++){
    buffer.putInt(block.rand[i]);
    }
    buffer.force();
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally{
    try {
    barrier.await();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    }
    public static void main(String[] args) throws Exception {
    final String fileName="D:\\tmp\\Test_3.data";
    final int count = 500000000;//生成随机数的个数 2,147,483,648
    final int max = 1000000;//随机数的最大值(不包括最大值)
    final int blockSize = 512*1024;//每个任务单元的大小(字节)
    final int randomThread = 1;Runtime.getRuntime().availableProcessors();//生成随机数的线程数
    final int writerThread = 1;Runtime.getRuntime().availableProcessors();//写入数据的线程数
    long start = System.currentTimeMillis();
    int maxNumberOfBlock = blockSize/4;//每个任务单元容纳的随机数的最大个数。
    BlockingQueue<Block> randomQueue = new ArrayBlockingQueue<Block>(randomThread);
    BlockingQueue<Block> writerQueue = new ArrayBlockingQueue<Block>(writerThread);
    RandomThread[] randomThreads = new RandomThread[randomThread];
    WriterThread[] writerThreads = new WriterThread[writerThread];
    CyclicBarrier randomBarrier = new CyclicBarrier(randomThread+1);
    for(int i=0;i<randomThread;i++){
    randomThreads[i] = new RandomThread(randomBarrier, randomQueue, writerQueue, max);
    randomThreads[i].start();
    }
    RandomAccessFile out = new RandomAccessFile(fileName,"rw");
    FileChannel channel = out.getChannel();
    CyclicBarrier writerBarrier = new CyclicBarrier(writerThread+1);
    for(int i=0;i<writerThread;i++){
    writerThreads[i] = new WriterThread(writerQueue, channel, writerBarrier);
    writerThreads[i].start();
    }
    int index = 0;
    for(int i=count;i>0;i-=maxNumberOfBlock){
    Block block = new Block();
    if(i>=maxNumberOfBlock){
    block.rand = new int[maxNumberOfBlock];
    block.index = index;
    index += maxNumberOfBlock;
    }else{
    block.rand = new int[i];
    block.index = index;
    index += i;
    }
    randomQueue.put(block);
    }
    for(int i=0;i<randomThread;i++){
    randomQueue.put(POISON);
    }
    randomBarrier.await();
    for(int i=0;i<writerThread;i++){
    writerQueue.put(POISON);
    }
    writerBarrier.await();
    channel.close();
    long end = System.currentTimeMillis();
    System.out.println(end-start);
    }}
      

  22.   

    坦克哥 我是要写10亿个最大为100万的随机整数,你这上面的代码是不是写错了啊for (int i = 0; i < n; i++) {
            int x = (int) (Math.random() * max);
            System.out.println(x);
            dos.writeInt(x);这里只写了100个
      

  23.   

    单线程的我也写了一个,不到4G的文件,耗时 58287 毫秒,这个速度可以接受了。
    import java.io.FileOutputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.util.Random;
    public class Test_4 { public static void main(String[] args) throws Exception {
    final String fileName="D:\\tmp\\Test_4.data";
    final int count = 1000000000;//生成随机数的个数 
    final int max = 1000000;//随机数的最大值(不包括最大值)
    final int bufferSize = 512*1024;//缓冲区的大小(字节)
    long start = System.currentTimeMillis();
    Random rand = new Random(System.currentTimeMillis());
    ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize);
    FileOutputStream out = new FileOutputStream(fileName);
    FileChannel channel = out.getChannel();
    for(int i=0;i<count;){
    buffer.clear();
    for(;buffer.limit()-buffer.position()>4 && i<count;i++){
    buffer.putInt(rand.nextInt(max));
    }
    buffer.flip();
    while(buffer.hasRemaining()) {
        channel.write(buffer);
    }
    buffer.rewind();
    }
    channel.close();
    out.close();
    long end = System.currentTimeMillis();
    System.out.println(end-start);
    //58287
    }}
      

  24.   

    为什么我用下面代码写入文件的只有1.26GFileWriter f=new FileWriter("D:/data.txt");
    BufferedWriter buf=new BufferedWriter(f,1024*512);
    int o=0;
    while(o<1000000000){
    buf.write((int) (Math.random()*1000000));
    o++;
    }
    buf.close();
      

  25.   


    buf.write((int) (Math.random()*1000000));
    write是写入一个byte这里的int被强转成byte了
      

  26.   


    public static void main(String[] args) throws Exception {
    write();
    //read();
    } static void write() throws Exception {
    long startTime = System.currentTimeMillis(); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c:/test.dat")); Random rad = new Random(); int max = 1000000;
    int count = 1000000000;
    //int count = 100; while (count-- > 0) {
    // int i = rad.nextInt(max);
    // bos.write(int2bytes(i));
    // System.out.print(i + "\t"); bos.write(int2bytes(rad.nextInt(max)));
    } bos.flush();
    bos.close(); System.out.println(System.currentTimeMillis() - startTime);
    } static void read() throws Exception {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream("c:/test.dat")); byte[] buff = new byte[4]; while (bis.read(buff) != -1) { int i = bytes2int(buff); // System.out.print(i + "\t");
    } bis.close();
    } static int bytes2int(byte[] b) {
    return ((b[0] & 0xff) << 24) + ((b[1] & 0xff) << 16) + ((b[2] & 0xff) << 8) + (b[3] & 0xff);
    } static byte[] int2bytes(int i) {
    byte[] rs = new byte[4]; rs[0] = (byte) ((i >>> 24) & 0xff);
    rs[1] = (byte) ((i >>> 16) & 0xff);
    rs[2] = (byte) ((i >>> 8) & 0xff);
    rs[3] = (byte) (i & 0xff); return rs;
    }
    发个修正版的,能跑到39967ms
      

  27.   

    楼主的代码中:
    buf.write((int) (Math.random()*1000000));
    这个语句的意思是,向缓冲区里面写入一个字节的数据,虽然参数是整形数据,但是,实际写入的是这个整数的低八位数据。
    因为,Java的byte类型数据,是有符号的,而底层数据处理,我们常常是用无符号的数据来运算处理,
    所以,为了兼容这个符号问题,就将参数定位整型数据了,
    因为,无论数值正负,整型的第八位数据于byte型数据是一致的。
      

  28.   

    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c:/test.dat"), 1024 * 1024 * 8);
    缓存设成8M硬盘一直处于写状态,耗时36109。
    缓存设大了硬盘反而一直空闲总耗时更多了。
      

  29.   

    而ByteBuffer这个类是专门为了处理底层数据而设计的,
    所以,用它向缓冲区里写入数据,整数就是4字节,byte就是一个字节,其他类型也保留了他们固有的数据格式。
    只是,网络通讯的时候,要注意一下字节序的问题。不过,一般不用太在意这个。
      

  30.   

    dd if=/dev/urandom of=./random_int bs=4 count=1000000000