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.



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();
  }
}





Copying a file using channels and buffers

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();
    }
  }
}





Create a read-only memory-mapped file

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());
  }
}





Create a read-write memory-mapped file

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());
  }
}





File concatenation based on new IO

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();
  }
}





Get FileChannel from FileInputStream

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();
  }
}





Lock a FileChannel and release the lock

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();
  }
}





Locking Copier

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();
  }
}





New IO Copier

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();
  }
}





New IO Duplicator

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();
  }
}





New IO Transfer

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();
  }
}





Save and read text using FileChannel without encoding

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();
  }
}





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

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());
    
  }
}
/**/



Some text


Test overlapping locks on different file channels

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");
  }
}





The Gathering Write

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();
  }
}





Using a Channel to Write a String to a File

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);
    }
  }
}





Using FileChannel to random access to a File

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;
    }
  }
}



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


Using FileChannel to read text file

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();
  }
}





Using transferTo() between channels

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());
  }
}





Writing and Appending a ByteBuffer to a File

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();
  }
}





Writing a String as Bytes

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);
    }
  }
}





Writing Mixed Data to a File

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);
    }
  }
}





Writing Numerical Data to a File

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);
    }
  }
}





Writing Varying Length Strings to a File

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);
    }
  }
}