我想请教的是如果我的inputStream对象中的数据比较多,比如几千万个btye,是将b初始化为所有数据长度,调用read方法一次写入所有的数据到数组中但是我数据过大的时候,会出现内存溢出的现象怎么通过缓存的方式一段一段的读取到byte[]数组中!!最好能给个实例

解决方案 »

  1.   

    //这是一个文件拷贝函数,参数例子tranFile(new File("C:\\temp\\a.txt"),new File("D:\\temp\\")),这个函数多大的文件都可以拷贝
    public boolean tranFile(File copy,File paste) throws IOException{
    //  System.out.println(paste.isFile()+"123");
    //  System.out.println(copy.isFile()+"456");
    if(!copy.isFile()||paste.isFile())
    return false;
    if(!paste.exists())
    paste.mkdirs();
    try{
    String separator="";
    separator=System.getProperties().getProperty("file.separator");
    System.out.println(paste.getPath());
    System.out.println(copy.getName());
    System.out.println(separator);
    InputStream in=new FileInputStream(copy);
    OutputStream out=new FileOutputStream(paste.getPath()+separator+copy.getName());
    byte b[]=new byte[1024];
    while(in.read(b,0,1024)!=-1)//这就是你要的重点了,这个read函数是每次读取1024个byte到b中,0的意思是从b[0]开始存数据
    {
    out.write(b);
    }
    in.close();
    out.close();
    }
    catch(Exception e)
    {
    System.out.println("你输入paste目录有问题!");
    return false;
    }


    return true;

    }
      

  2.   


    BufferedInputStream bufr = new BufferedInputStream(new InputStream("d:\\1.txt"));
    byte [] buf = new byte[1024*1024]; //每次读取1M,(这边好像不可太大)
    int len = 0;
    while((len=bufr.read(buf))!=-1)
    {
    //code
    }
      

  3.   

    如果你要把所有数据都存储到byte[]数组中。无论你采取什么方式读。肯定都会超内存。因为内存就那么大,你byte[] 占的又是内存的空间。必然超。楼上的方法,没仔细看。估计是把数据存储到了外存上。但是楼主你的实际需求是什么?
      

  4.   

            [修正]BufferedInputStream bufr = new BufferedInputStream(new FileInputStream("d:\\1.txt"));
      

  5.   

    现在的情况是这样的,从控制器搞来的InputStream我要读取里面的字节,假设142个字节为一条指令,我知道一共有32条指令就是4544个字节,但是通过
        public void writeStoreData() throws IOException {
           int a = 0;//指令数
           while (inputStream.available()>0){
                storeData = new byte[inputStream.available()];
                for (int i=0;i<inputStream.available();i++){
                 inputStream.read(storeData,i,142);
                //满足条件指令就累加
                if (storeData[i]==104||storeData[i+1]==103||storeData[i+2]==43||){
                  a++;
               }
               }
            System.out.println(a);
           }
        }
    按照理论讲inputstream.available()应该为4544但是我断点看了下实际只有4094,少了部分数据,结果指令只有29条了。。这要怎么办
      

  6.   

    看看文件是否有错吧,你这才4K多个字节怎么可能就丢失了。就是你再大几倍也不会出现这种情况。
    建议:
    1.确认输入;
    2.用debug逐行检查,看看是否有哪里的逻辑或数据出了问题
      

  7.   

    你最后有没有把输入流和输出流关闭呢?
    好像字节流不关闭会出现一些错误的吧
    4K很小没什么关系的
    大文件不是一般逐个逐个读入输出的吗?
    FileInputStream in=new FileInputStream(f);
    FileOutputStream out=new FileOutputStream(f2);
    int temp=0;
    while((temp=in.read())!=-1){
    out.write(temp);
    }
    in.close();
    out.close();
      

  8.   

    使用缓冲区 
    byte[] vBuffer =  new byte[2048];
    int vReadCount = 0;
    while((vReadCount = vInputStream.read(vBuffer)) != -1){
              vOutputStream.write(vbuffer, 0, vReadCount);
    }楼主有兴趣的话可以查一下inputStream/outPutStream 的api
      

  9.   

     public void writeStoreData() throws IOException {
            System.out.print("OK*********");
            int a = 0;
            storeData = new byte[512*1024];
            while (inputStream.read(storeData,i,142)!=-1){
                if (storeData[i]==104||storeData[i+1]==103||storeData[i+2]==43||storeData[i+3]==104||
                storeData[i+4]==1||storeData[i+5]==1){
                  a++;
                  System.out.print(a+"*");
                }
               i+=142;
            }
            outputStream.close();
            inputStream.close();
        }
    刚改了下,不过也没什么用字节数组都512K了
      

  10.   


    几千万个Byte?假设为5千万Byte,也就是这个数据需要50MB的内存空间才能正常存储(不算辅助空间的话)。
    楼主够狠的啊,能确定需求真的必须这么玩么?最好重新审视需求。如果你确定必须这么玩的话,建议如下:
    1、建立一个缓存数组,类似你代码中的storeData,容量不同太大,4096就好了;
    2、建立ByteArrayOutputStream;
    3、将所有批次读取的storeData数据直接写入ByteArrayOutputStream;
    4、循环3完成后,所有数据就都在ByteArrayOutputStream里面了,你可以toByteArray()拿出来慢慢玩。最重要的:java虚拟机启动参数必须加上:  -Xmx512m  否则必然OOM。
      

  11.   


    是说你6楼的代码么?你能解释下,你这句话中的i企图用来干什么的? “inputStream.read(storeData,i,142);”
      

  12.   

    我用来读取从 假如i初始是0(i是变量),我就用它来读取从0到141的字节并存入字节数组storeDate,然后就是循环了(i+142)开始共142个字节存入数组storeDate
      

  13.   

    我的思路就是直接从输入流inputStream里面读一段字节,然后存一段字节放入storeDate这里肯定足够大的字节数组
      

  14.   

    岂不是后面的直接覆盖前面的?但又没有完全覆盖,每次都留1个字节,好吧,这个也不算是最大问题。比较有意思的问题是循环本身:
    for (int i=0;i<inputStream.available();i++)
    假定inputStream.available()的预期值是4544,那么也就意味着你这个循环会循环 4544次,对吧?
    但你每次要求读取142个字节,也就意味着你总共企图读取645248个字节。但是更有意思的是,其实随着你每次循环读取,你的inputStream.available()是在不断减少的,对吧?
    也就是随着i的不断增加,你的i<inputStream.available()右边这个值却在不断减小,这个循环的效果就很动态化或者戏剧化了。所以我很想不通你究竟想实现什么效果另外还有个小问题是,你能确定 inputStream.read(storeData,i,142); 读取的都是142个字节长么?你的流是永不阻塞型的么?建议: int len = inputStream.read(storeData,i,142);
    并把len打印出来,尤其是len!=142 的打印出来。
      

  15.   

    public void writeStoreData() throws IOException {
      System.out.print("OK*********");
      int a = 0;
      storeData = new byte[512*1024];
      while (inputStream.read(storeData,i,142)!=-1){
      if (storeData[i]==104||storeData[i+1]==103||storeData[i+2]==43||storeData[i+3]==104||
      storeData[i+4]==1||storeData[i+5]==1){
      a++;
      System.out.print(a+"*");
      }
      i+=142;
      }
      outputStream.close();
      inputStream.close();
      }
    已经改过了,不会有留1个字节第一次存入(0~141)共142个之后是i+142开始.......你上面还是讲的还是挺有用的
      

  16.   


    看了半天是旧版本的,汗新版本的大逻辑上貌似没啥问题,唯一的漏洞就仅在:while (inputStream.read(storeData,i,142)!=-1) 这里了,因为read函数不保证一定完整读取142字节长;所以还是建议修改为:
    while ((len=(inputStream.read(storeData,i,142))!=-1)
    然后 i+=len;
      

  17.   

    既然每次都只读142字节,为什么你要建立一个这么大的缓冲区?...不解...
    inputStream.read(storeData,i,142))!=-1 流结尾,这个难道不报错吗?标准流读取写法:
    int size = 0;
    byte[] buf = new byte[142];
    while((size = inputStream.read(buf)) != -1) {
     // 流的处理 buf缓冲区可用数据部分为 - buf[0] ~ buf[size-1]
     // 这里处理你的缓冲区
    }
      

  18.   

    我的inputStream里面数据是512*1024个字节,我需要的是每142个字节(作为一条指令)进行相关处理,inputStream.read(storeData,i,142))i是变量从输入流里读取142个字节处理,并存入数组storeData,我输入流数据字节要和我存放字节的数组storeData一样大才行吧,所以缓冲做这么大
      

  19.   

    缓冲是作为一个快速响应机制来运作的,而不是让你当做数据容器来用的....
    你是字符指令串吗? 好吧,假设你是字符式的指令List<String> commandList = new ArrayList<String>(512);
    int size = 0;
    byte[] buf = new byte[142];
    while((size = inputStream.read(buf)) != -1) {
     // 假设你的字符是String,其他指令可以自己构建一个指令对象
     commandList.add(new String(buf,0,size));
    }for(String command : commandList){
     // 处理指令列表
    }
      

  20.   


    // 指令结构
    class Command {
     public byte[] data;
     public Command(byte[] data) {
      this.data = data;
     }
    }// 处理代码
    List<Command> commandList = new ArrayList<Command>(512);
    int size = 0;
    byte[] buf = new byte[142];
    while((size = inputStream.read(buf)) != -1) {
     byte[] data = new byte[size];
     System.arraycopy(buf, 0, data, 0, size)
     commandList.add(new Command(data));
    }for(Command command : commandList){
     // 处理指令列表
    }
      

  21.   


    你仔细看API了没?inputStream.available只是告诉你缓存区现有可读字节,不是所有字节。
    你把这4096个字节读了之后,再看inputStream.available 就能找到那剩下的29个了。
      

  22.   


    看了半天是旧版本的,汗新版本的大逻辑上貌似没啥问题,唯一的漏洞就仅在:while (inputStream.read(storeData,i,142)!=-1) 这里了,因为read函数不保证一定完整读取142字节长;所以还是建议修改为:
    while ((len=(inputStream.read(storeData,i,142))!=-1)
    然后 i+=len;

    这位ldh911果然学识渊博,这几天已经从你的几个回答里受教了