java 内存映射处理大文件

Java中用内存映射处理大文件

2012-06-20 14:16 tobacco5648 tobacco5648博客 字号:T |T
一键收藏,随时查看,分享好友!

在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如下为一个对比实验。

AD: 51CTO 网+ 第十二期沙龙:大话数据之美_如何用数据驱动用户体验


在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如下为一个对比实验。

    
    
  1. package test;  
  2.  
  3. import java.io.BufferedInputStream;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.IOException;  
  7. import java.io.RandomAccessFile;  
  8. import java.nio.MappedByteBuffer;  
  9. import java.nio.channels.FileChannel;  
  10.  
  11. public class Test {  
  12.  
  13.       
  14.     public static void main(String[] args) {  
  15.         try {  
  16.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
  17.             int sum=0;  
  18.             int n;  
  19.             long t1=System.currentTimeMillis();  
  20.             try {  
  21.                 while((n=fis.read())>=0){  
  22.                     sum+=n;  
  23.                 }  
  24.             } catch (IOException e) {  
  25.                 // TODO Auto-generated catch block  
  26.                 e.printStackTrace();  
  27.             }  
  28.             long t=System.currentTimeMillis()-t1;  
  29.             System.out.println("sum:"+sum+"  time:"+t);  
  30.         } catch (FileNotFoundException e) {  
  31.             // TODO Auto-generated catch block  
  32.             e.printStackTrace();  
  33.         }  
  34.           
  35.         try {  
  36.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
  37.             BufferedInputStream bis=new BufferedInputStream(fis);  
  38.             int sum=0;  
  39.             int n;  
  40.             long t1=System.currentTimeMillis();  
  41.             try {  
  42.                 while((n=bis.read())>=0){  
  43.                     sum+=n;  
  44.                 }  
  45.             } catch (IOException e) {  
  46.                 // TODO Auto-generated catch block  
  47.                 e.printStackTrace();  
  48.             }  
  49.             long t=System.currentTimeMillis()-t1;  
  50.             System.out.println("sum:"+sum+"  time:"+t);  
  51.         } catch (FileNotFoundException e) {  
  52.             // TODO Auto-generated catch block  
  53.             e.printStackTrace();  
  54.         }  
  55.           
  56.         MappedByteBuffer buffer=null;  
  57.         try {  
  58.             buffer=new RandomAccessFile("/home/tobacco/test/res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 01253244);  
  59.             int sum=0;  
  60.             int n;  
  61.             long t1=System.currentTimeMillis();  
  62.             for(int i=0;i<1253244;i++){  
  63.                 n=0x000000ff&buffer.get(i);  
  64.                 sum+=n;  
  65.             }  
  66.             long t=System.currentTimeMillis()-t1;  
  67.             System.out.println("sum:"+sum+"  time:"+t);  
  68.         } catch (FileNotFoundException e) {  
  69.             // TODO Auto-generated catch block  
  70.             e.printStackTrace();  
  71.         } catch (IOException e) {  
  72.             // TODO Auto-generated catch block  
  73.             e.printStackTrace();  
  74.         }  
  75.  
  76.     }  
  77.  
  78. }  

测试文件为一个大小为1253244字节的文件。测试结果:

    
    
  1. sum:220152087 time:1464  
  2. sum:220152087 time:72  
  3. sum:220152087 time:25 

说明读数据无误。删去其中的数据处理部分。

    
    
  1. package test;  
  2.  
  3. import java.io.BufferedInputStream;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.IOException;  
  7. import java.io.RandomAccessFile;  
  8. import java.nio.MappedByteBuffer;  
  9. import java.nio.channels.FileChannel;  
  10.  
  11. public class Test {  
  12.  
  13.       
  14.     public static void main(String[] args) {  
  15.         try {  
  16.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
  17.             int sum=0;  
  18.             int n;  
  19.             long t1=System.currentTimeMillis();  
  20.             try {  
  21.                 while((n=fis.read())>=0){  
  22.                     //sum+=n;  
  23.                 }  
  24.             } catch (IOException e) {  
  25.                 // TODO Auto-generated catch block  
  26.                 e.printStackTrace();  
  27.             }  
  28.             long t=System.currentTimeMillis()-t1;  
  29.             System.out.println("sum:"+sum+"  time:"+t);  
  30.         } catch (FileNotFoundException e) {  
  31.             // TODO Auto-generated catch block  
  32.             e.printStackTrace();  
  33.         }  
  34.           
  35.         try {  
  36.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
  37.             BufferedInputStream bis=new BufferedInputStream(fis);  
  38.             int sum=0;  
  39.             int n;  
  40.             long t1=System.currentTimeMillis();  
  41.             try {  
  42.                 while((n=bis.read())>=0){  
  43.                     //sum+=n;  
  44.                 }  
  45.             } catch (IOException e) {  
  46.                 // TODO Auto-generated catch block  
  47.                 e.printStackTrace();  
  48.             }  
  49.             long t=System.currentTimeMillis()-t1;  
  50.             System.out.println("sum:"+sum+"  time:"+t);  
  51.         } catch (FileNotFoundException e) {  
  52.             // TODO Auto-generated catch block  
  53.             e.printStackTrace();  
  54.         }  
  55.           
  56.         MappedByteBuffer buffer=null;  
  57.         try {  
  58.             buffer=new RandomAccessFile("/home/tobacco/test/res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 01253244);  
  59.             int sum=0;  
  60.             int n;  
  61.             long t1=System.currentTimeMillis();  
  62.             for(int i=0;i<1253244;i++){  
  63.                 //n=0x000000ff&buffer.get(i);  
  64.                 //sum+=n;  
  65.             }  
  66.             long t=System.currentTimeMillis()-t1;  
  67.             System.out.println("sum:"+sum+"  time:"+t);  
  68.         } catch (FileNotFoundException e) {  
  69.             // TODO Auto-generated catch block  
  70.             e.printStackTrace();  
  71.         } catch (IOException e) {  
  72.             // TODO Auto-generated catch block  
  73.             e.printStackTrace();  
  74.         }  
  75.  
  76.     }  
  77.  

测试结果:

    
    
  1. sum:0 time:1458  
  2. sum:0 time:67  
  3. sum:0 time:8 

由此可见,将文件部分或者全部映射到内存后进行读写,速度将提高很多。

这是因为内存映射文件首先将外存上的文件映射到内存中的一块连续区域,被当成一个字节数组进行处理,读写操作直接对内存进行操作,而后再将内存区域重新映射到外存文件,这就节省了中间频繁的对外存进行读写的时间,大大降低了读写时间。

原文链接:http://blog.csdn.net/tobacco5648/article/details/7679105

 

 

 

使用Java处理大文件

我最近要处理一套存储历史实时数据的大文件fx market data,我很快便意识到,使用传统的InputStream不能够将它们读取到内存,因为每一个文件都超过了4G。甚至编辑器都不能够打开这些文件。

在这种特殊情况下,我可以写一个简单的bash脚本将这些文件分成更小的文件块,然后再读取它。但是我不想这样做,因为二进制格式会使这个方法失效。

处理这个问题的方式通常就是使用内存映射文件递增地处理区域的数据。关于内存映射文件的一个好处就是它们不会使用虚拟内存和换页空间,因为它们是从磁盘上的文件返回来的数据。

很好,让我们来看一看这些文件和额外的一些数据。似乎它们使用逗号分隔的字段包含ASCII文本行。

格式:[currency-pair],[timestamp],[bid-price],[ask-price]

例子:EUR/USD,20120102 00:01:30.420,1.29451,1.2949

我可以为这种格式去写一个程序,但是,读取文件和解析文件是无关的概念。让我们退一步来想一个通用的设计,当在将来面临相似的问题时这个设计可以被重复利用。

这个问题可以归结为递增地解码一个已经在无限长的数组中被编码的记录,并且没有耗尽内存。实际上,以逗号分割的示例格式编码与通常的解决方案是不相关的。所以,很明显需要一个解码器来处理不同的格式。

再来看,知道整个文件处理完成,每一条记录都不能被解析并保存在内存中,所以我们需要一种方式来转移记录,在它们成为垃圾被回收之前可以被写到其他地方,例如磁盘或者网络。

迭代器是处理这个需求的很好的抽象,因为它们就像游标一样,可以正确的指向某个位置。每一次迭代都可以转发文件指针,并且可以让我们使用数据做其他的事情。

首先来写一个Decoder 接口,递增地把对象从MappedByteBuffer中解码,如果buffer中没有对象,则返回null。

1
2
3
public interface Decoder<T> {
     public T decode(ByteBuffer buffer);
}

然后让FileReader 实现Iterable接口。每一个迭代器将会处理下一个4096字节的数据,并使用Decoder把它们解码成一个对象的List集合。注意,FileReader 接收文件(files)的list对象,这样是很好的,因为它可以遍历数据,并且不需要考虑聚合的问题。顺便说一下,4096个字节块对于大文件来说是非常小的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class FileReader implements Iterable<List<T>> {
   private static final long CHUNK_SIZE = 4096 ;
   private final Decoder<T> decoder;
   private Iterator<File> files;
  
   private FileReader(Decoder<T> decoder, File... files) {
     this (decoder, Arrays.asList(files));
   }
   private FileReader(Decoder<T> decoder, List<File> files) {
     this .files = files.iterator();
     this .decoder = decoder;
   }
   public static <T> FileReader<T> create(Decoder<T> decoder, List<File> files) {
     return new FileReader<T>(decoder, files);
   }
  
   public static <T> FileReader<T> create(Decoder<T> decoder, File... files) {
     return new FileReader<T>(decoder, files);
   }
   @Override
   public Iterator<List<T>> iterator() {
     return new Iterator<List<T>>() {
       private List<T> entries;
       private long chunkPos = 0 ;
       private MappedByteBuffer buffer;
       private FileChannel channel;
       @Override
       public boolean hasNext() {
         if (buffer == null || !buffer.hasRemaining()) {
           buffer = nextBuffer(chunkPos);
           if (buffer == null ) {
             return false ;
           }
         }
         T result = null ;
         while ((result = decoder.decode(buffer)) != null ) {
           if (entries == null ) {
             entries = new ArrayList<T>();
           }
           entries.add(result);
         }
         // set next MappedByteBuffer chunk
         chunkPos += buffer.position();
         buffer = null ;
         if (entries != null ) {
           return true ;
         } else {
           Closeables.closeQuietly(channel);
           return false ;
         }
       }
  
       private MappedByteBuffer nextBuffer( long position) {
         try {
           if (channel == null || channel.size() == position) {
             if (channel != null ) {
               Closeables.closeQuietly(channel);
               channel = null ;
             }
             if (files.hasNext()) {
               File file = files.next();
               channel = new RandomAccessFile(file, "r" ).getChannel();
               chunkPos = 0 ;
               position = 0 ;
             } else {
               return null ;
             }
           }
           long chunkSize = CHUNK_SIZE;
           if (channel.size() - position < chunkSize) {
             chunkSize = channel.size() - position;
           }
            return channel.map(FileChannel.MapMode.READ_ONLY, chunkPos, chunkSize);
         } catch (IOException e) {
            Closeables.closeQuietly(channel);
            throw new RuntimeException(e);
         }
       }
  
       @Override
       public List<T> next() {
         List<T> res = entries;
         entries = null ;
         return res;
       }
  
       @Override
       public void remove() {
         throw new UnsupportedOperationException();
       }
     };
   }
}

下一个任务就是写一个Decoder 。针对逗号分隔的任何文本格式,编写一个TextRowDecoder 类。接收的参数是每行字段的数量和一个字段分隔符,返回byte的二维数组。TextRowDecoder 可以被操作不同字符集的特定格式解码器重复利用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class TextRowDecoder implements Decoder< byte [][]> {
   private static final byte LF = 10 ;
   private final int numFields;
   private final byte delimiter;
   public TextRowDecoder( int numFields, byte delimiter) {
    this .numFields = numFields;
    this .delimiter = delimiter;
   }
   @Override
   public byte [][] decode(ByteBuffer buffer) {
     int lineStartPos = buffer.position();
     int limit = buffer.limit();
     while (buffer.hasRemaining()) {
       byte b = buffer.get();
       if (b == LF) { // reached line feed so parse line
         int lineEndPos = buffer.position();
         // set positions for one row duplication
         if (buffer.limit() < lineEndPos + 1 ) {
           buffer.position(lineStartPos).limit(lineEndPos);
         } else {
           buffer.position(lineStartPos).limit(lineEndPos + 1 );
         }
         byte [][] entry = parseRow(buffer.duplicate());
         if (entry != null ) {
           // reset main buffer
           buffer.position(lineEndPos);
           buffer.limit(limit);
           // set start after LF
           lineStartPos = lineEndPos;
         }
         return entry;
       }
     }
     buffer.position(lineStartPos);
     return null ;
   }
   
   public byte [][] parseRow(ByteBuffer buffer) {
     int fieldStartPos = buffer.position();
     int fieldEndPos = 0 ;
     int fieldNumber = 0 ;
     byte [][] fields = new byte [numFields][];
     while (buffer.hasRemaining()) {
       byte b = buffer.get();
       if (b == delimiter || b == LF) {
         fieldEndPos = buffer.position();
         // save limit
         int limit = buffer.limit();
         // set positions for one row duplication
         buffer.position(fieldStartPos).limit(fieldEndPos);
         fields[fieldNumber] = parseField(buffer.duplicate(), fieldNumber, fieldEndPos - fieldStartPos - 1 );
         fieldNumber++;
         // reset main buffer
         buffer.position(fieldEndPos);
         buffer.limit(limit);
         // set start after LF
         fieldStartPos = fieldEndPos;
       }
       if (fieldNumber == numFields) {
         return fields;
       }
     }
     return null ;
   }
   
   private byte [] parseField(ByteBuffer buffer, int pos, int length) {
     byte [] field = new byte [length];
     for ( int i = 0 ; i < field.length; i++) {
       field[i] = buffer.get();
     }
     return field;
   }
}

这是文件被处理的过程。每一个List包含的元素都从一个单独的buffer中解码,每一个元素都是被TextRowDecoder定义的byte二维数组。

1
2
3
4
5
TextRowDecoder decoder = new TextRowDecoder( 4 , comma);
FileReader< byte [][]> reader = FileReader.create(decoder, file.listFiles());
for (List< byte [][]> chunk : reader) {
   // do something with each chunk
}

我们可以在这里打住,不过还有额外的需求。每一行都包含一个时间戳,每一批都必须分组,使用时间段来代替buffers,如按照天分组、或者按照小时分组。我还想要遍历每一批的数据,因此,第一反应就是,为FileReader创建一个Iterable包装器,实现它的行为。一个额外的细节,每一个元素必须通过实现Timestamped接口(这里没有显示)提供时间戳到PeriodEntries。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
       
   public class PeriodEntries<T extends Timestamped> implements Iterable<List<T>> {
   private final Iterator<List<T extends Timestamped>> entriesIt;
   private final long interval;
   private PeriodEntries(Iterable<List<T>> entriesIt, long interval) {
     this .entriesIt = entriesIt.iterator();
     this .interval = interval;
   }
  
   public static <T extends Timestamped> PeriodEntries<T> create(Iterable<List<T>> entriesIt, long interval) {
    return new PeriodEntries<T>(entriesIt, interval);
   }
  
   @Override
   public Iterator<List<T extends Timestamped>> iterator() {
     return new Iterator<List<T>>() {
       private Queue<List<T>> queue = new LinkedList<List<T>>();
       private long previous;
       private Iterator<T> entryIt;
  
       @Override
       public boolean hasNext() {
         if (!advanceEntries()) {
           return false ;
         }
         T entry =  entryIt.next();
         long time = normalizeInterval(entry);
         if (previous == 0 ) {
           previous = time;
         }
         if (queue.peek() == null ) {
           List<T> group = new ArrayList<T>();
           queue.add(group);
         }
         while (previous == time) {
           queue.peek().add(entry);
           if (!advanceEntries()) {
             break ;
           }
           entry = entryIt.next();
           time = normalizeInterval(entry);
         }
         previous = time;
         List<T> result = queue.peek();
         if (result == null || result.isEmpty()) {
           return false ;
         }
         return true ;
       }
  
       private boolean advanceEntries() {
         // if there are no rows left
         if (entryIt == null || !entryIt.hasNext()) {
           // try get more rows if possible
           if (entriesIt.hasNext()) {
             entryIt = entriesIt.next().iterator();
             return true ;
           } else {
             // no more rows
             return false ;
           }
         }
         return true ;
       }
  
       private long normalizeInterval(Timestamped entry) {
         long time = entry.getTime();
         int utcOffset = TimeZone.getDefault().getOffset(time);
         long utcTime = time + utcOffset;
         long elapsed = utcTime % interval;
         return time - elapsed;
       }
       @Override
       public List<T> next() {
         return queue.poll();
       }
       @Override
       public void remove() {
         throw new UnsupportedOperationException();
       }
    };
   }
}

最后的处理代码通过引入这个函数并无太大变动,只有一个干净的且紧密的循环,不必关心文件、缓冲区、时间周期的分组元素。PeriodEntries也是足够的灵活管理任何时长的时间。

1
2
3
4
5
6
7
8
9
10
11
TrueFxDecoder decoder = new TrueFxDecoder();
FileReader<TrueFxData> reader = FileReader.create(decoder, file.listFiles());
long periodLength = TimeUnit.DAYS.toMillis( 1 );
PeriodEntries<TrueFxData> periods = PeriodEntries.create(reader, periodLength);
   
for (List<TrueFxData> entries : periods) {
    // data for each day
    for (TrueFxData entry : entries) {
      // process each entry
    }
}

你也许意识到了,使用集合不可能解决这样的问题;选择迭代器是一个关键的设计决策,能够解析兆字节的数组,且不会消耗过多的空间。

原文链接: javacodegeeks 翻译: ImportNew.com - 踏雁寻花
译文链接: http://www.importnew.com/10712.html
[ 转载请保留原文出处、译者和译文链接。]

关于作者: 踏雁寻花

个人主页:踏雁寻花 | 记录生活、工作、学习的一个挨踢人的博客 新浪微博:@踏雁寻花

查看踏雁寻花的更多文章 >>

 

 

 

java读写文件

    import java.io.BufferedOutputStream;

    import  java.io.BufferedReader;

    import java.io.File;

    import java.io.FileOutputStream;

   import java.io.FileReader;

   import java.io.FileWriter;

   import java.io.IOException;

   import java.io.OutputStreamWriter;


     public void ReadFile(String filename) {

          File file=new File(filename);

         BufferedReader reader=null;

      try{

               reader=new BufferedReader(new FileReader(file));   //如果是读大文件  则  new BufferedReader(new FileReader(file),5*1024*1024);  即,设置缓存

               String tempString=null;

               while((tempString=reader.readLine())!=null)

               {

                    //进行操作.....

              }

            reader.close();

       }catch(IOException e){

             e.printStackTrace();

      }finally{

           if(reader!=null)

         {

               try{

                      reader.close();

               }catch(IOException e)

             {

             e.printStackTrace();

            }

          }

       }

}

二、写文件

    import java.io.BufferedOutputStream;

    import  java.io.BufferedReader;

   import  java.io.BufferedWriter;

    import java.io.File;

    import java.io.FileOutputStream;

   import java.io.FileReader;

   import java.io.FileWriter;

   import java.io.IOException;

   import java.io.OutputStreamWriter;


    public void method1(String file,String content){

     BufferedWriter out=null;

     try{

           out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file,true)));  //追加的方法

          out.write(content);

          out.write("\r\n");

   }catch(IOException e){

             e.printStackTrace();

      }finally{

     try{

    out.close();

  }catch(IOException e){

             e.printStackTrace();

      }

}

}


public void main(String[] args)

{

   String filename="D:\a.txt";

  File f=new File(filename);

 if(f.exists()){

    f.delete();

}

f.createNewFile();

String ss="sssssss";

method1(filename,ss);

}


===========================华丽丽的分隔符=============================

在实践中发现上面的方法最多也就能处理10M以内的数据,从而编辑此文章。

想要真正处理上百M,甚至上G的文件,那就要用到java的nio包:

下面的代码转自【http://www.oschina.net/code/snippet_54100_7938】

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.RandomAccessFile; 
import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel; 


public class TestNio { 

public static void main(String args[]) throws Exception{ 
int bufSize = 100; 
File fin = new File("D:\\workspace\\test\\usagetracking.log"); 
File fout = new File("D:\\workspace\\test\\usagetracking2.log"); 


FileChannel fcin = new RandomAccessFile(fin, "r").getChannel(); 
ByteBuffer rBuffer = ByteBuffer.allocate(bufSize); 


FileChannel fcout = new RandomAccessFile(fout, "rws").getChannel(); 
ByteBuffer wBuffer = ByteBuffer.allocateDirect(bufSize); 




readFileByLine(bufSize, fcin, rBuffer, fcout, wBuffer); 


System.out.print("OK!!!"); 


/*读文件同时写文件*/
public static void readFileByLine(int bufSize, FileChannel fcin, ByteBuffer rBuffer, FileChannel fcout, ByteBuffer wBuffer){ 
String enterStr = "\n"; 
try{ 
byte[] bs = new byte[bufSize]; 


int size = 0; 
StringBuffer strBuf = new StringBuffer(""); 
//while((size = fcin.read(buffer)) != -1){ 
while(fcin.read(rBuffer) != -1){ 
     int rSize = rBuffer.position(); 
     rBuffer.rewind(); 
     rBuffer.get(bs); 
     rBuffer.clear(); 
     String tempString = new String(bs, 0, rSize); 
     //System.out.print(tempString); 
     //System.out.print("<200>"); 


     int fromIndex = 0; 
     int endIndex = 0; 
     while((endIndex = tempString.indexOf(enterStr, fromIndex)) != -1){ 
      String line = tempString.substring(fromIndex, endIndex); 
      line = new String(strBuf.toString() + line); 
      //System.out.print(line); 
      //System.out.print("</over/>"); 
      //write to anthone file 
      writeFileByLine(fcout, wBuffer, line); 


      
      strBuf.delete(0, strBuf.length()); 
      fromIndex = endIndex + 1; 
     } 
     if(rSize > tempString.length()){ 
     strBuf.append(tempString.substring(fromIndex, tempString.length())); 
     }else{ 
     strBuf.append(tempString.substring(fromIndex, rSize)); 
     } 

} catch (IOException e) { 
// TODO Auto-generated catch block 
e.printStackTrace(); 



/*写文件*/
public static void writeFileByLine(FileChannel fcout, ByteBuffer wBuffer, String line){ 
try { 
//write on file head 
//fcout.write(wBuffer.wrap(line.getBytes())); 
//wirte append file on foot 
fcout.write(wBuffer.wrap(line.getBytes()), fcout.size()); 


} catch (IOException e) { 
// TODO Auto-generated catch block 
e.printStackTrace(); 





 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值