Java Tutorial/File/FileChannel

Материал из Java эксперт
Перейти к: навигация, поиск

A channel for a physical file

A channel for a physical file: provides an efficient mechanism for reading, writing, and manipulating the file.



   <source lang="java">

import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] a) {
   File aFile = new File("C:/myFile.text");
   FileOutputStream outputFile = null; // Place to store an output stream
                                       // reference
   try {
     // Create the stream opened to write
     outputFile = new FileOutputStream(aFile);
   } catch (FileNotFoundException e) {
     e.printStackTrace(System.err);
     System.exit(1);
   }
   // Get the channel for the file
   FileChannel outputChannel = outputFile.getChannel();
 }

}</source>





Copying a file using channels and buffers

   <source lang="java">

import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class MainClass {

 private static final int BSIZE = 1024;
 public static void main(String[] args) throws Exception {
   FileChannel in = new FileInputStream("source.txt").getChannel(), out = new FileOutputStream(
       "target.txt").getChannel();
   ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
   while (in.read(buffer) != -1) {
     buffer.flip();
     out.write(buffer);
     buffer.clear();
   }
 }

}</source>





Create a read-only memory-mapped file

   <source lang="java">

import java.io.File; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class Main {

 public static void main(String[] argv) throws Exception {
   File file = new File("filename");
   FileChannel roChannel = new RandomAccessFile(file, "r").getChannel();
   ByteBuffer roBuf = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, (int) roChannel.size());
 }

}</source>





Create a read-write memory-mapped file

   <source lang="java">

import java.io.File; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class Main {

 public static void main(String[] argv) throws Exception {
   FileChannel rwChannel = new RandomAccessFile(new File("test.txt"), "rw").getChannel();
   ByteBuffer wrBuf = rwChannel.map(FileChannel.MapMode.READ_WRITE, 0, (int) rwChannel.size());
 }

}</source>





File concatenation based on new IO

   <source lang="java">

import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) throws IOException {
   if (args.length < 2) {
     System.err.println("Usage: java MainClass inFile1 inFile2... outFile");
     return;
   }
   ByteBuffer[] buffers = new ByteBuffer[args.length - 1];
   for (int i = 0; i < args.length - 1; i++) {
     RandomAccessFile raf = new RandomAccessFile(args[i], "r");
     FileChannel channel = raf.getChannel();
     buffers[i] = channel.map(FileChannel.MapMode.READ_ONLY, 0, raf.length());
   }
   FileOutputStream outFile = new FileOutputStream(args[args.length - 1]);
   FileChannel out = outFile.getChannel();
   out.write(buffers);
   out.close();
 }

}</source>





Get FileChannel from FileInputStream

   <source lang="java">

import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.IntBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) throws IOException {
   FileChannel fc = new FileInputStream(new File("temp.tmp")).getChannel();
   IntBuffer ib = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()).asIntBuffer();
   while (ib.hasRemaining())
     ib.get();
   fc.close();
 }

}</source>





Lock a FileChannel and release the lock

   <source lang="java">

import java.io.FileOutputStream; import java.nio.channels.FileLock; public class MainClass {

 public static void main(String[] args) throws Exception {
   FileOutputStream fos = new FileOutputStream("file.txt");
   FileLock fl = fos.getChannel().tryLock();
   if (fl != null) {
     System.out.println("Locked File");
     Thread.sleep(100);
     fl.release();
     System.out.println("Released Lock");
   }
   fos.close();
 }

}</source>





Locking Copier

   <source lang="java">

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; public class MainClass {

 public static void main(String[] args) throws IOException {
   FileInputStream inFile = new FileInputStream(args[0]);
   FileOutputStream outFile = new FileOutputStream(args[1]);
   FileChannel inChannel = inFile.getChannel();
   FileChannel outChannel = outFile.getChannel();
   FileLock outLock = outChannel.lock();
   FileLock inLock = inChannel.lock(0, inChannel.size(), true);
   inChannel.transferTo(0, inChannel.size(), outChannel);
   outLock.release();
   inLock.release();
   inChannel.close();
   outChannel.close();
 }

}</source>





New IO Copier

   <source lang="java">

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) throws IOException {
   FileInputStream inFile = new FileInputStream(args[0]);
   FileOutputStream outFile = new FileOutputStream(args[1]);
   FileChannel inChannel = inFile.getChannel();
   FileChannel outChannel = outFile.getChannel();
   for (ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); inChannel.read(buffer) != -1; buffer
       .clear()) {
     buffer.flip();
     while (buffer.hasRemaining())
       outChannel.write(buffer);
   }
   inChannel.close();
   outChannel.close();
 }

}</source>





New IO Duplicator

   <source lang="java">

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) throws IOException {
   FileInputStream inFile = new FileInputStream(args[0]);
   FileOutputStream outFile = new FileOutputStream(args[1]);
   FileChannel inChannel = inFile.getChannel();
   FileChannel outChannel = outFile.getChannel();
   ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
   int bytesRead = 0;
   while (bytesRead >= 0 || buffer.hasRemaining()) {
     if (bytesRead != -1)
       bytesRead = inChannel.read(buffer);
     buffer.flip();
     outChannel.write(buffer);
     buffer.rupact();
   }
   inChannel.close();
   outChannel.close();
 }

}</source>





New IO Transfer

   <source lang="java">

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) throws IOException {
   FileInputStream inFile = new FileInputStream(args[0]);
   FileOutputStream outFile = new FileOutputStream(args[1]);
   FileChannel inChannel = inFile.getChannel();
   FileChannel outChannel = outFile.getChannel();
   inChannel.transferTo(0, inChannel.size(), outChannel);
   inChannel.close();
   outChannel.close();
 }

}</source>





Save and read text using FileChannel without encoding

   <source lang="java">

import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; public class MainClass {

 private static final int BSIZE = 1024;
 public static void main(String[] args) throws Exception {
   FileChannel fc = new FileOutputStream("data2.txt").getChannel();
   fc.write(ByteBuffer.wrap("Some text".getBytes()));
   fc.close();
   fc = new FileInputStream("data2.txt").getChannel();
   ByteBuffer buff = ByteBuffer.allocate(BSIZE);
   fc.read(buff);
   buff.flip();
   System.out.println(buff.asCharBuffer());
   // Decode using this system"s default Charset:
   buff.rewind();
   String encoding = System.getProperty("file.encoding");
   System.out.println("Decoded using " + encoding + ": " + Charset.forName(encoding).decode(buff));
   // Or, we could encode with something that will print:
   fc = new FileOutputStream("data2.txt").getChannel();
   fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16BE")));
   fc.close();
 }

}</source>





Save and read text using FileChannel with UTF-16BE encoding

   <source lang="java">

import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; public class MainClass {

 private static final int BSIZE = 1024;
 public static void main(String[] args) throws Exception {
   FileChannel fc = new FileOutputStream("data2.txt").getChannel();
   fc.write(ByteBuffer.wrap(
     "Some text".getBytes("UTF-16BE")));
   fc.close();
   ByteBuffer buff = ByteBuffer.allocate(BSIZE);
   // Now try reading again:
   fc = new FileInputStream("data2.txt").getChannel();
   buff.clear();
   fc.read(buff);
   buff.flip();
   System.out.println(buff.asCharBuffer());
   
 }

} /**/</source>



Some text


Test overlapping locks on different file channels

   <source lang="java">

import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; public class MainClass {

 public static void main(String[] argv) throws Exception {
   String filename = "test.dat";
   RandomAccessFile raf1 = new RandomAccessFile(filename, "rw");
   FileChannel fc1 = raf1.getChannel();
   RandomAccessFile raf2 = new RandomAccessFile(filename, "rw");
   FileChannel fc2 = raf2.getChannel();
   System.out.println("Grabbing first lock");
   FileLock lock1 = fc1.lock(0L, Integer.MAX_VALUE, false);
   System.out.println("Grabbing second lock");
   FileLock lock2 = fc2.lock(5, 10, false);
   System.out.println("Exiting");
 }

}</source>





The Gathering Write

   <source lang="java">

import java.io.File; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) {
   try {
     test();
   } catch (Exception e) {
     e.printStackTrace();
   }
 }
 private static void test() throws Exception {
   long[] primes = new long[] { 1, 2, 3, 5, 7 };
   File aFile = new File("C:/test/primes.txt");
   FileOutputStream outputFile = null;
   outputFile = new FileOutputStream(aFile);
   FileChannel file = outputFile.getChannel();
   ByteBuffer[] buffers = new ByteBuffer[3];
   buffers[0] = ByteBuffer.allocate(8);
   buffers[2] = ByteBuffer.allocate(8);
   String primeStr = null;
   for (long prime : primes) {
     primeStr = "prime = " + prime;
     buffers[0].putDouble((double) primeStr.length()).flip();
     buffers[1] = ByteBuffer.allocate(primeStr.length());
     buffers[1].put(primeStr.getBytes()).flip();
     buffers[2].putLong(prime).flip();
     file.write(buffers);
     buffers[0].clear();
     buffers[2].clear();
   }
   System.out.println("File written is " + file.size() + "bytes.");
   outputFile.close();
 }

}</source>





Using a Channel to Write a String to a File

   <source lang="java">

import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) {
   String phrase = new String("text \n");
   String dirname = "C:/test"; 
   String filename = "charData.txt"; 
   File dir = new File(dirname); 
   File aFile = new File(dir, filename); 
   FileOutputStream outputFile = null; 
   try {
     outputFile = new FileOutputStream(aFile, true);
     System.out.println("File stream created successfully.");
   } catch (FileNotFoundException e) {
     e.printStackTrace(System.err);
   }
   FileChannel outChannel = outputFile.getChannel();
   ByteBuffer buf = ByteBuffer.allocate(1024);
   System.out.println("New buffer:           position = " + buf.position() + "\tLimit = "
       + buf.limit() + "\tcapacity = " + buf.capacity());
   for (char ch : phrase.toCharArray()) {
     buf.putChar(ch);
   }
   System.out.println("Buffer after loading: position = " + buf.position() + "\tLimit = "
       + buf.limit() + "\tcapacity = " + buf.capacity());
   buf.flip(); 
   System.out.println("Buffer after flip:   position = " + buf.position() + "\tLimit = "
       + buf.limit() + "\tcapacity = " + buf.capacity());
   try {
     outChannel.write(buf);
     outputFile.close(); 
     System.out.println("Buffer contents written to file.");
   } catch (IOException e) {
     e.printStackTrace(System.err);
   }
 }

}</source>





Using FileChannel to random access to a File

   <source lang="java">

import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.LongBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) throws Exception {
   createFile();
   File aFile = new File("C:/primes.bin");
   FileInputStream inFile = new FileInputStream(aFile);
   FileChannel inChannel = inFile.getChannel();
   final int PRIMESREQUIRED = 10;
   ByteBuffer buf = ByteBuffer.allocate(8 * PRIMESREQUIRED);
   long[] primes = new long[PRIMESREQUIRED];
   int index = 0; // Position for a prime in the file
   // Count of primes in the file
   final int PRIMECOUNT = (int) inChannel.size() / 8;
   // Read the number of random primes required
   for (int i = 0; i < PRIMESREQUIRED; i++) {
     index = 8 * (int) (PRIMECOUNT * Math.random());
     inChannel.read(buf, index); // Read the value
     buf.flip();
     primes[i] = buf.getLong(); // Save it in the array
     buf.clear();
   }
   for (long prime : primes) {
     System.out.printf("%12d", prime);
   }
   inFile.close(); // Close the file and the channel
 }
 private static void createFile() throws Exception {
   long[] primes = new long[] { 1, 2, 3, 5, 7 };
   File aFile = new File("C:/primes.bin");
   FileOutputStream outputFile = new FileOutputStream(aFile);
   FileChannel file = outputFile.getChannel();
   final int BUFFERSIZE = 100;
   ByteBuffer buf = ByteBuffer.allocate(BUFFERSIZE);
   LongBuffer longBuf = buf.asLongBuffer();
   int primesWritten = 0;
   while (primesWritten < primes.length) {
     longBuf.put(primes, primesWritten, min(longBuf.capacity(), primes.length - primesWritten));
     buf.limit(8 * longBuf.position());
     file.write(buf);
     primesWritten += longBuf.position();
     longBuf.clear();
     buf.clear();
   }
   System.out.println("File written is " + file.size() + "bytes.");
   outputFile.close();
 }
 private static int min(int a, int b) {
   if (a > b) {
     return b;
   } else {
     return a;
   }
 }

}</source>



File written is 40bytes.
           3           5           1           7           7           5           7           1           7           1


Using FileChannel to read text file

   <source lang="java">

import java.io.File; import java.io.FileInputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) throws Exception {
   File aFile = new File("charData.xml");
   FileInputStream inFile = null;
   inFile = new FileInputStream(aFile);
   FileChannel inChannel = inFile.getChannel();
   ByteBuffer buf = ByteBuffer.allocate(48);
   while (inChannel.read(buf) != -1) {
     System.out.println("String read: " + ((ByteBuffer) (buf.flip())).asCharBuffer().get(0));
     buf.clear();
   }
   inFile.close();
 }

}</source>





Using transferTo() between channels

   <source lang="java">

import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) throws Exception {
   FileChannel in = new FileInputStream("source.txt").getChannel(), out = new FileOutputStream(
       "target.txt").getChannel();
   in.transferTo(0, in.size(), out);
   // Or:
   // out.transferFrom(in, 0, in.size());
 }

}</source>





Writing and Appending a ByteBuffer to a File

   <source lang="java">

import java.io.File; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class Main {

 public static void main(String[] argv) throws Exception {
   ByteBuffer bbuf = ByteBuffer.allocate(100);
   File file = new File("filename");
   boolean append = false;
   FileChannel wChannel = new FileOutputStream(file, append).getChannel();
   wChannel.write(bbuf);
   wChannel.close();
 }

}</source>





Writing a String as Bytes

   <source lang="java">

import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) {
   String phrase = new String("text\n");
   String dirname = "C:/test"; // Directory name
   String filename = "byteData.txt";
   File aFile = new File(dirname, filename);
   // Create the file output stream
   FileOutputStream file = null;
   try {
     file = new FileOutputStream(aFile, true);
   } catch (FileNotFoundException e) {
     e.printStackTrace(System.err);
   }
   FileChannel outChannel = file.getChannel();
   ByteBuffer buf = ByteBuffer.allocate(phrase.length());
   byte[] bytes = phrase.getBytes();
   buf.put(bytes);
   buf.flip();
   try {
     outChannel.write(buf);
     file.close();
   } catch (IOException e) {
     e.printStackTrace(System.err);
   }
 }

}</source>





Writing Mixed Data to a File

   <source lang="java">

import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.LongBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) {
   long[] primes = new long[] { 1, 2, 3, 5, 7 };
   File aFile = new File("C:/test/primes.txt");
   FileOutputStream outputFile = null;
   try {
     outputFile = new FileOutputStream(aFile);
   } catch (FileNotFoundException e) {
     e.printStackTrace(System.err);
   }
   FileChannel file = outputFile.getChannel();
   final int BUFFERSIZE = 100;
   ByteBuffer buf = ByteBuffer.allocate(BUFFERSIZE);
   DoubleBuffer doubleBuf = buf.asDoubleBuffer();
   buf.position(8);
   CharBuffer charBuf = buf.asCharBuffer();
   for (long prime : primes) {
     String primeStr = "prime = " + prime;
     doubleBuf.put(0, (double) primeStr.length());
     charBuf.put(primeStr);
     buf.position(2 * charBuf.position() + 8);
     LongBuffer longBuf = buf.asLongBuffer();
     longBuf.put(prime);
     buf.position(buf.position() + 8);
     buf.flip();
     try {
       file.write(buf);
     } catch (IOException e) {
       e.printStackTrace(System.err);
     }
     buf.clear();
     doubleBuf.clear();
     charBuf.clear();
   }
   try {
     System.out.println("File written is " + file.size() + "bytes.");
     outputFile.close();
   } catch (IOException e) {
     e.printStackTrace(System.err);
   }
 }

}</source>





Writing Numerical Data to a File

   <source lang="java">

import static java.lang.Math.min; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.LongBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) {
   long[] primes = new long[] { 1, 2, 3, 5, 7 };
   File aFile = new File("C:/test/primes.bin");
   FileOutputStream outputFile = null;
   try {
     outputFile = new FileOutputStream(aFile);
   } catch (FileNotFoundException e) {
     e.printStackTrace(System.err);
   }
   FileChannel file = outputFile.getChannel();
   final int BUFFERSIZE = 100;
   ByteBuffer buf = ByteBuffer.allocate(BUFFERSIZE);
   LongBuffer longBuf = buf.asLongBuffer();
   int primesWritten = 0;
   while (primesWritten < primes.length) {
     longBuf.put(primes, primesWritten, min(longBuf.capacity(), primes.length - primesWritten));
     buf.limit(8 * longBuf.position());
     try {
       file.write(buf);
       primesWritten += longBuf.position();
     } catch (IOException e) {
       e.printStackTrace(System.err);
     }
     longBuf.clear();
     buf.clear();
   }
   try {
     System.out.println("File written is " + file.size() + "bytes.");
     outputFile.close();
   } catch (IOException e) {
     e.printStackTrace(System.err);
   }
 }

}</source>





Writing Varying Length Strings to a File

   <source lang="java">

import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class MainClass {

 public static void main(String[] args) {
   String dirName = "c:/test";
   String fileName = "test.txt";
   String[] sayings = { "A1", "B12", "C123", "D1234", "E12345", "F123456", "G1234567" };
   File aFile = new File(dirName, fileName);
   FileOutputStream outputFile = null;
   try {
     outputFile = new FileOutputStream(aFile, true);
   } catch (FileNotFoundException e) {
     e.printStackTrace(System.err);
     System.exit(1);
   }
   FileChannel outChannel = outputFile.getChannel();
   int maxLength = 0;
   for (String saying : sayings) {
     if (maxLength < saying.length()){
       maxLength = saying.length();
     }
   }
   ByteBuffer buf = ByteBuffer.allocate(2 * maxLength + 4);
   try {
     for (String saying : sayings) {
       buf.putInt(saying.length()).asCharBuffer().put(saying);
       buf.position(buf.position() + 2 * saying.length()).flip();
       outChannel.write(buf);
       buf.clear();
     }
     outputFile.close();
   } catch (IOException e) {
     e.printStackTrace(System.err);
   }
 }

}</source>