用java 里面写的可执行文件怎么里面加的素材图片不能显示?

10581人阅读
file(内存)----输入流----&【程序】----输出流----&file(内存)
当我们读写文本文件的时候,采用Reader是非常方便的,比如FileReader,InputStreamReader和BufferedReader。其中最重要的类是InputStreamReader, 它是字节转换为字符的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如GBK等。使用FileReader读取文件:
FileReader fr = new FileReader(&ming.txt&);
int ch = 0;
while((ch = fr.read())!=-1 )
System.out.print((char)ch);
其中read()方法返回的是读取得下个字符。当然你也可以使用read(char[] ch,int off,int length)这和处理二进制文件的时候类似。
事实上在FileReader中的方法都是从InputStreamReader中继承过来的。read()方法是比较好费时间的,如果为了提高效率我们可以使用BufferedReader对Reader进行包装,这样可以提高读取得速度,我们可以一行一行的读取文本,使用readLine()方法。
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(&ming.txt&)));
String data =
while((data = br.readLine())!=null)
System.out.println(data);
了解了FileReader操作使用FileWriter写文件就简单了,这里不赘述。
Eg.我的综合实例
import java.io.F
import java.io.FileInputS
import java.io.FileNotFoundE
import java.io.FileOutputS
import java.io.IOE
import java.io.InputStreamR
public class testFile {
* @param args
public static void main(String[] args) {
// TODO Auto-generated method stub
// file(内存)----输入流----&【程序】----输出流----&file(内存)
File file = new File(&d:/temp&, &addfile.txt&);
file.createNewFile(); // 创建文件
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// 向文件写入内容(输出流)
String str = &亲爱的小南瓜!&;
byte bt[] = new byte[1024];
bt = str.getBytes();
FileOutputStream in = new FileOutputStream(file);
in.write(bt, 0, bt.length);
in.close();
// boolean success=
// System.out.println(&写入文件成功&);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// 读取文件内容 (输入流)
FileInputStream out = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(out);
int ch = 0;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
} catch (Exception e) {
// TODO: handle exception
java中多种方式读文件
//------------------参考资料---------------------------------
//1、按字节读取文件内容
//2、按字符读取文件内容
//3、按行读取文件内容
//4、随机读取文件内容
import java.io.BufferedR
import java.io.F
import java.io.FileInputS
import java.io.FileR
import java.io.IOE
import java.io.InputS
import java.io.InputStreamR
import java.io.RandomAccessF
import java.io.R
public class ReadFromFile {
* 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。
* @param fileName
public static void readFileByBytes(String fileName) {
File file = new File(fileName);
InputStream in =
System.out.println(&以字节为单位读取文件内容,一次读一个字节:&);
// 一次读一个字节
in = new FileInputStream(file);
while ((tempbyte = in.read()) != -1) {
System.out.write(tempbyte);
in.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println(&以字节为单位读取文件内容,一次读多个字节:&);
// 一次读多个字节
byte[] tempbytes = new byte[100];
int byteread = 0;
in = new FileInputStream(fileName);
ReadFromFile.showAvailableBytes(in);
// 读入多个字节到字节数组中,byteread为一次读入的字节数
while ((byteread = in.read(tempbytes)) != -1) {
System.out.write(tempbytes, 0, byteread);
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (in != null) {
in.close();
} catch (IOException e1) {
* 以字符为单位读取文件,常用于读文本,数字等类型的文件
* @param fileName
public static void readFileByChars(String fileName) {
File file = new File(fileName);
Reader reader =
System.out.println(&以字符为单位读取文件内容,一次读一个字节:&);
// 一次读一个字符
reader = new InputStreamReader(new FileInputStream(file));
while ((tempchar = reader.read()) != -1) {
// 对于windows下,rn这两个字符在一起时,表示一个换行。
// 但如果这两个字符分开显示时,会换两次行。
// 因此,屏蔽掉r,或者屏蔽n。否则,将会多出很多空行。
if (((char) tempchar) != 'r') {
System.out.print((char) tempchar);
reader.close();
} catch (Exception e) {
e.printStackTrace();
System.out.println(&以字符为单位读取文件内容,一次读多个字节:&);
// 一次读多个字符
char[] tempchars = new char[30];
int charread = 0;
reader = new InputStreamReader(new FileInputStream(fileName));
// 读入多个字符到字符数组中,charread为一次读取字符数
while ((charread = reader.read(tempchars)) != -1) {
// 同样屏蔽掉r不显示
if ((charread == tempchars.length)
&& (tempchars[tempchars.length - 1] != 'r')) {
System.out.print(tempchars);
for (int i = 0; i & i++) {
if (tempchars[i] == 'r') {
System.out.print(tempchars[i]);
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (reader != null) {
reader.close();
} catch (IOException e1) {
* 以行为单位读取文件,常用于读面向行的格式化文件
* @param fileName
public static void readFileByLines(String fileName) {
File file = new File(fileName);
BufferedReader reader =
System.out.println(&以行为单位读取文件内容,一次读一整行:&);
reader = new BufferedReader(new FileReader(file));
String tempString =
int line = 1;
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null) {
// 显示行号
System.out.println(&line & + line + &: & + tempString);
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
} catch (IOException e1) {
* 随机读取文件内容
* @param fileName
public static void readFileByRandomAccess(String fileName) {
RandomAccessFile randomFile =
System.out.println(&随机读取一段文件内容:&);
// 打开一个随机访问文件流,按只读方式
randomFile = new RandomAccessFile(fileName, &r&);
// 文件长度,字节数
long fileLength = randomFile.length();
// 读文件的起始位置
int beginIndex = (fileLength & 4) ? 4 : 0;
// 将读文件的开始位置移到beginIndex位置。
randomFile.seek(beginIndex);
byte[] bytes = new byte[10];
int byteread = 0;
// 一次读10个字节,如果文件内容不足10个字节,则读剩下的字节。
// 将一次读取的字节数赋给byteread
while ((byteread = randomFile.read(bytes)) != -1) {
System.out.write(bytes, 0, byteread);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (randomFile != null) {
randomFile.close();
} catch (IOException e1) {
* 显示输入流中还剩的字节数
* @param in
private static void showAvailableBytes(InputStream in) {
System.out.println(&当前字节输入流中的字节数为:& + in.available());
} catch (IOException e) {
e.printStackTrace();
public static void main(String[] args) {
String fileName = &C:/temp/newTemp.txt&;
ReadFromFile.readFileByBytes(fileName);
ReadFromFile.readFileByChars(fileName);
ReadFromFile.readFileByLines(fileName);
ReadFromFile.readFileByRandomAccess(fileName);
//二、将内容追加到文件尾部
import java.io.FileW
import java.io.IOE
import java.io.RandomAccessF
* 将内容追加到文件尾部
public class AppendToFile {
* A方法追加文件:使用RandomAccessFile
* @param fileName
* @param content
追加的内容
public static void appendMethodA(String fileName,
String content) {
// 打开一个随机访问文件流,按读写方式
RandomAccessFile randomFile = new RandomAccessFile(fileName, &rw&);
// 文件长度,字节数
long fileLength = randomFile.length();
// 将写文件指针移到文件尾。
randomFile.seek(fileLength);
randomFile.writeBytes(content);
randomFile.close();
} catch (IOException e) {
e.printStackTrace();
* B方法追加文件:使用FileWriter
* @param fileName
* @param content
public static void appendMethodB(String fileName, String content) {
// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
FileWriter writer = new FileWriter(fileName, true);
writer.write(content);
writer.close();
} catch (IOException e) {
e.printStackTrace();
public static void main(String[] args) {
String fileName = &C:/temp/newTemp.txt&;
String content = &new append!&;
// 按方法A追加文件
AppendToFile.appendMethodA(fileName, content);
AppendToFile.appendMethodA(fileName, &append end. n&);
// 显示文件内容
ReadFromFile.readFileByLines(fileName);
// 按方法B追加文件
AppendToFile.appendMethodB(fileName, content);
AppendToFile.appendMethodB(fileName, &append end. n&);
// 显示文件内容
ReadFromFile.readFileByLines(fileName);
1、判断文件是否存在,不存在创建文件
File file=new File(path+filename);
if(!file.exists())
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
2、判断文件夹是否存在,不存在创建文件夹
File file =new File(path+filename);
//如果文件夹不存在则创建
(!file .exists())
file .mkdir();
import java.io.F
import java.io.FileOutputS
import java.io.*;
public class FileTest {
public FileTest() {
public static void main(String[] args) {
FileOutputStream out =
FileOutputStream outSTr =
BufferedOutputStream Buff=
FileWriter fw =
int count=1000;//写文件行数
out = new FileOutputStream(new File(“C:/add.txt”));
long begin = System.currentTimeMillis();
for (int i = 0; i & i++) {
out.write(“测试java 文件操作\r\n”.getBytes());
out.close();
long end = System.currentTimeMillis();
System.out.println(“FileOutputStream执行耗时:” + (end - begin) + ” 豪秒”);
outSTr = new FileOutputStream(new File(“C:/add0.txt”));
Buff=new BufferedOutputStream(outSTr);
long begin0 = System.currentTimeMillis();
for (int i = 0; i & i++) {
Buff.write(“测试java 文件操作\r\n”.getBytes());
Buff.flush();
Buff.close();
long end0 = System.currentTimeMillis();
System.out.println(“BufferedOutputStream执行耗时:” + (end0 - begin0) + ” 豪秒”);
fw = new FileWriter(“C:/add2.txt”);
long begin3 = System.currentTimeMillis();
for (int i = 0; i & i++) {
fw.write(“测试java 文件操作\r\n”);
fw.close();
long end3 = System.currentTimeMillis();
System.out.println(“FileWriter执行耗时:” + (end3 - begin3) + ” 豪秒”);
} catch (Exception e) {
e.printStackTrace();
fw.close();
Buff.close();
outSTr.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
String name = &AAAA.txt&;
String lujing = &1&+&/&+&2&;//定义路径
File a = new File(lujing,name);
a.getParentFile().mkdirs();&&& //这里如果不加getParentFile(),创建的文件夹为&1/2/AAAA.txt/&
那么,a的意义就是“1/2/AAAA.txt”。
这里a是File,但是File这个类在Java里表示的不只是文件,虽然File在英语里是文件的意思。Java里,File至少可以表示文件或文件夹(大概还有可以表示系统设备什么的,这里不考虑,只考虑文件和文件夹)。
也就是说,在“1/2/AAAA.txt”真正出现在磁盘结构里之前,它既可以表示这个文件,也可以表示这个路径的文件夹。那么,如果没有getParentFile(),直接执行a.mkdirs(),就是说,创建“1/2/AAAA.txt”代表的文件夹,也就是“1/2/AAAA.txt/”,在此之后,执行a.createNewFile(),试图创建a文件,然而以a为名的文件夹已经存在了,所以createNewFile()实际是执行失败的。你可以用System.out.println(a.createNewFile())这样来检查是不是真正创建文件成功。
所以,这里,你想要创建的是“1/2/AAAA.txt”这个文件。在创建AAAA.txt之前,必须要1/2这个目录存在。所以,要得到1/2,就要用a.getParentFile(),然后要创建它,也就是a.getParentFile().mkdirs()。在这之后,a作为文件所需要的文件夹大概会存在了(有特殊情况会无法创建的,这里不考虑),就执行a.createNewFile()创建a文件。
Java RandomAccessFile的使用
Java的RandomAccessFile提供对文件的读写功能,与普通的输入输出流不一样的是RamdomAccessFile可以任意的访问文件的任何地方。这就是“Random”的意义所在。
RandomAccessFile的对象包含一个记录指针,用于标识当前流的读写位置,这个位置可以向前移动,也可以向后移动。RandomAccessFile包含两个方法来操作文件记录指针。
long getFilePoint():记录文件指针的当前位置。
void seek(long pos):将文件记录指针定位到pos位置。
RandomAccessFile包含InputStream的三个read方法,也包含OutputStream的三个write方法。同时RandomAccessFile还包含一系列的readXxx和writeXxx方法完成输入输出。
RandomAccessFile的构造方法如下
mode的值有四个
&r&:以只读文方式打开指定文件。如果你写的话会有IOException。
&rw&:以读写方式打开指定文件,不存在就创建新文件。
&rws&:不介绍了。
&rwd&:也不介绍。
* 往文件中依次写入3名员工的信息,
* 每位员工有姓名和员工两个字段 然后按照
* 第二名,第一名,第三名的先后顺序读取员工信息
import java.io.F
import java.io.RandomAccessF
public class RandomAccessFileTest {
public static void main(String[] args) throws Exception {
Employee e1 = new Employee(23, &张三&);
Employee e2 = new Employee(24, &lisi&);
Employee e3 = new Employee(25, &王五&);
File file = new File(&employee.txt&);
if (!file.exists()) {
file.createNewFile();
// 一个中文占两个字节 一个英文字母占一个字节
// 整形 占的字节数目 跟cpu位长有关 32位的占4个字节
RandomAccessFile randomAccessFile = new RandomAccessFile(file, &rw&);
randomAccessFile.writeChars(e1.getName());
randomAccessFile.writeInt(e1.getAge());
randomAccessFile.writeChars(e2.getName());
randomAccessFile.writeInt(e2.getAge());
randomAccessFile.writeChars(e3.getName());
randomAccessFile.writeInt(e3.getAge());
randomAccessFile.close();
RandomAccessFile raf2 = new RandomAccessFile(file, &r&);
raf2.skipBytes(Employee.LEN * 2 + 4);
String strName2 = &&;
for (int i = 0; i & Employee.LEN; i++) {
strName2 = strName2 + raf2.readChar();
int age2 = raf2.readInt();
System.out.println(&strName2 = & + strName2.trim());
System.out.println(&age2 = & + age2);
raf2.seek(0);
String strName1 = &&;
for (int i = 0; i & Employee.LEN; i++) {
strName1 = strName1 + raf2.readChar();
int age1 = raf2.readInt();
System.out.println(&strName1 = & + strName1.trim());
System.out.println(&age1 = & + age1);
raf2.skipBytes(Employee.LEN * 2 + 4);
String strName3 = &&;
for (int i = 0; i & Employee.LEN; i++) {
strName3 = strName3 + raf2.readChar();
int age3 = raf2.readInt();
System.out.println(&strName3 = & + strName3.trim());
System.out.println(&age3 = & + age3);
class Employee {
// 姓名的长度
public static final int LEN = 8;
public Employee(int age, String name) {
this.age =
// 对name字符长度的一个处理
if (name.length() & LEN) {
name = name.substring(0, LEN);
while (name.length() & LEN) {
name = name + &/u0000&;
this.name =
public int getAge() {
public String getName() {
RandomAccessFile类。其I/O性能较之其它常用开发语言的同类性能差距甚远,严重影响程序的运行效率。
开发人员迫切需要提高效率,下面分析RandomAccessFile等文件类的源代码,找出其中的症结所在,并加以改进优化,创建一个&性/价比&俱佳的随机文件访问类BufferedRandomAccessFile。
在改进之前先做一个基本测试:逐字节COPY一个12兆的文件(这里牵涉到读和写)。
耗用时间(秒)
RandomAccessFile
RandomAccessFile
BufferedInputStream + DataInputStream
BufferedOutputStream + DataOutputStream
我们可以看到两者差距约32倍,RandomAccessFile也太慢了。先看看两者关键部分的源代码,对比分析,找出原因。
1.1.[RandomAccessFile]
Java代码 &
public&class&RandomAccessFile&implements&DataOutput,&DataInput&{&&&&&&public&final&byte&readByte()&throws&IOException&{&&&&&&&&&&int&ch&=&this.read();&&&&&&&&&&if&(ch&&&0)&&&&&&&&&&&&&&throw&new&EOFException();&&&&&&&&&&return&(byte)(ch);&&&&&&}&&&&&&public&native&int&read()&throws&IOE&&&&&&&public&final&void&writeByte(int&v)&throws&IOException&{&&&&&&&&&&write(v);&&&&&&}&&&&&&&public&native&void&write(int&b)&throws&IOE&&&}&&
可见,RandomAccessFile每读/写一个字节就需对磁盘进行一次I/O操作。
1.2.[BufferedInputStream]
Java代码 &
public&class&BufferedInputStream&extends&FilterInputStream&{&&&&&&private&static&int&defaultBufferSize&=&2048;&&&&&&&protected&byte&buf[];&&&&&&&public&BufferedInputStream(InputStream&in,&int&size)&{&&&&&&&&&&super(in);&&&&&&&&&&&&&&&&&&if&(size&&=&0)&{&&&&&&&&&&&&&&throw&new&IllegalArgumentException(&Buffer&size&&=&0&);&&&&&&&&&&}&&&&&&&&&&buf&=&new&byte[size];&&&&&&}&&&&&&public&synchronized&int&read()&throws&IOException&{&&&&&&&&&&ensureOpen();&&&&&&&&&&if&(pos&&=&count)&{&&&&&&&&&&&&&&fill();&&&&&&&&&&&&&&if&(pos&&=&count)&&&&&&&&&&&&&&&&&&return&-1;&&&&&&&&&&}&&&&&&&&&&return&buf[pos++]&&&0xff;&&&&&&&}&&&&&&&private&void&fill()&throws&IOException&{&&&&&&if&(markpos&&&0)&&&&&&&&&&pos&=&0;&&&&&&&&&&&&&&else&if&(pos&&=&buf.length)&&&&&&&&&&&&if&(markpos&&&0)&{&&&&&&&&&&&&&int&sz&=&pos&-&&&&&&&&&&&System.arraycopy(buf,&markpos,&buf,&0,&sz);&&&&&&&&&&pos&=&&&&&&&&&&&markpos&=&0;&&&&&&&&&&}&else&if&(buf.length&&=&marklimit)&{&&&&&&&&&&markpos&=&-1;&&&&&&&&&&&&&pos&=&0;&&&&&&&&&&&&&&}&else&{&&&&&&&&&&&&&&&&&&int&nsz&=&pos&*&2;&&&&&&&&&&if&(nsz&&&marklimit)&&&&&&&&&&&&&&nsz&=&&&&&&&&&&&byte&nbuf[]&=&new&byte[nsz];&&&&&&&&&&System.arraycopy(buf,&0,&nbuf,&0,&pos);&&&&&&&&&&buf&=&&&&&&&&&&&}&&&&&&count&=&&&&&&&int&n&=&in.read(buf,&pos,&buf.length&-&pos);&&&&&&if&(n&&&0)&&&&&&&&&&count&=&n&+&&&&&&&}&&}&&
1.3.[BufferedOutputStream]
Java代码 &
public&class&BufferedOutputStream&extends&FilterOutputStream&{&&&&&protected&byte&buf[];&&&&&&public&BufferedOutputStream(OutputStream&out,&int&size)&{&&&&&&&&&&super(out);&&&&&&&&&&if&(size&&=&0)&{&&&&&&&&&&&&&&throw&new&IllegalArgumentException(&Buffer&size&&=&0&);&&&&&&&&&&}&&&&&&&&&&buf&=&new&byte[size];&&&&&&}&&&public&synchronized&void&write(int&b)&throws&IOException&{&&&&&&&&&&if&(count&&=&buf.length)&{&&&&&&&&&&&&&&flushBuffer();&&&&&&&&&&}&&&&&&&&&&buf[count++]&=&(byte)b;&&&&&&}&&&&&private&void&flushBuffer()&throws&IOException&{&&&&&&&&&&if&(count&&&0)&{&&&&&&&&&&&&&&out.write(buf,&0,&count);&&&&&&&&&&&&&&count&=&0;&&&&&&&&&&}&&&&&}&&}&&
可见,Buffered I/O putStream每读/写一个字节,若要操作的数据在BUF中,就直接对内存的buf[]进行读/写操作;否则从磁盘相应位置填充buf[],再直接对内存的buf[]进行读/写操作,绝大部分的读/写操作是对内存buf[]的操作。
1.3.小结
内存存取时间单位是纳秒级(10E-9),磁盘存取时间单位是毫秒级(10E-3),同样操作一次的开销,内存比磁盘快了百万倍。理论上可以预见,即使对内存操作上万次,花费的时间也远少对于磁盘一次I/O的开销。显然后者是通过增加位于内存的BUF存取,减少磁盘I/O的开销,提高存取效率的,当然这样也增加了BUF控制部分的开销。从实际应用来看,存取效率提高了32倍。
根据1.3得出的结论,现试着对RandomAccessFile类也加上缓冲读写机制。
随机访问类与顺序类不同,前者是通过实现DataInput/DataOutput接口创建的,而后者是扩展FilterInputStream/FilterOutputStream创建的,不能直接照搬。
2.1.开辟缓冲区BUF[默认:1024字节],用作读/写的共用缓冲区。
2.2.先实现读缓冲。
读缓冲逻辑的基本原理:
A 欲读文件POS位置的一个字节。
B 查BUF中是否存在?若有,直接从BUF中读取,并返回该字符BYTE。
C 若没有,则BUF重新定位到该POS所在的位置并把该位置附近的BUFSIZE的字节的文件内容填充BUFFER,返回B。
以下给出关键部分代码及其说明:
Java代码 &
public&class&BufferedRandomAccessFile&extends&RandomAccessFile&{&&&&&&&&&&&&public&byte&read(long&pos)&throws&IOException&{&&&&&&&&&&if&(pos&&&this.bufstartpos&||&pos&&&this.bufendpos&)&{&&&&&&&&&&&&&&this.flushbuf();&&&&&&&&&&&&&&this.seek(pos);&&&&&&&&&&&&&&if&((pos&&&this.bufstartpos)&||&(pos&&&this.bufendpos))&&&&&&&&&&&&&&&&&&&throw&new&IOException();&&&&&&&&&&}&&&&&&&&&&this.curpos&=&&&&&&&&&&&return&this.buf[(int)(pos&-&this.bufstartpos)];&&&&&&}&&&&&&&&private&void&flushbuf()&throws&IOException&{&&&&&&&&&&if&(this.bufdirty&==&true)&{&&&&&&&&&&&&&&if&(super.getFilePointer()&!=&this.bufstartpos)&{&&&&&&&&&&&&&&&&&&super.seek(this.bufstartpos);&&&&&&&&&&&&&&}&&&&&&&&&&&&&&super.write(this.buf,&0,&this.bufusedsize);&&&&&&&&&&&&&&this.bufdirty&=&false;&&&&&&&&&&}&&&&&&}&&&&&&&&public&void&seek(long&pos)&throws&IOException&{&&&&&&&&&&if&((pos&&&this.bufstartpos)&||&(pos&&&this.bufendpos))&{&&&&&&&&&&&&&&&this.flushbuf();&&&&&&&&&&&&&&if&((pos&&=&0)&&&&(pos&&=&this.fileendpos)&&&&(this.fileendpos&!=&0))&{&&&&&&&&&&&&&&&&&&&&&&&this.bufstartpos&=&&pos&*&bufbitlen&/&&&&&&&&&&&&&&&&&&&&&this.bufusedsize&=&this.fillbuf();&&&&&&&&&&&&&&}&else&if&(((pos&==&0)&&&&(this.fileendpos&==&0))&||&(pos&==&this.fileendpos&+&1))&{&&&&&&&&&&&&&&&&&&&&&this.bufstartpos&=&&&&&&&&&&&&&&&&&&&this.bufusedsize&=&0;&&&&&&&&&&&&&&}&&&&&&&&&&&&&&this.bufendpos&=&this.bufstartpos&+&this.bufsize&-&1;&&&&&&&&&&}&&&&&&&&&&this.curpos&=&&&&&&&}&&&&&&&&private&int&fillbuf()&throws&IOException&{&&&&&&&&&&super.seek(this.bufstartpos);&&&&&&&&&&this.bufdirty&=&false;&&&&&&&&&&return&super.read(this.buf);&&&&&&}&&}&&
至此缓冲读基本实现,逐字节COPY一个12兆的文件(这里牵涉到读和写,用BufferedRandomAccessFile试一下读的速度):
耗用时间(秒)
RandomAccessFile
RandomAccessFile
BufferedRandomAccessFile
BufferedOutputStream + DataOutputStream
BufferedInputStream + DataInputStream
BufferedOutputStream + DataOutputStream
可见速度显著提高,与BufferedInputStream+DataInputStream不相上下。
2.3.实现写缓冲。
写缓冲逻辑的基本原理:
A欲写文件POS位置的一个字节。
B 查BUF中是否有该映射?若有,直接向BUF中写入,并返回true。
C若没有,则BUF重新定位到该POS所在的位置,并把该位置附近的 BUFSIZE字节的文件内容填充BUFFER,返回B。
下面给出关键部分代码及其说明:
Java代码 &
&&&&&&&&&&public&boolean&write(byte&bw,&long&pos)&throws&IOException&{&&&&&&&&&&if&((pos&&=&this.bufstartpos)&&&&(pos&&=&this.bufendpos))&{&&&&&&&&&&&&&&&this.buf[(int)(pos&-&this.bufstartpos)]&=&&&&&&&&&&&&&&&this.bufdirty&=&true;&&&&&&&&&&&&&&if&(pos&==&this.fileendpos&+&1)&{&&&&&&&&&&&&&&&&&&&this.fileendpos++;&&&&&&&&&&&&&&&&&&this.bufusedsize++;&&&&&&&&&&&&&&}&&&&&&&&&&}&else&{&&&&&&&&&&&&&&&this.seek(pos);&&&&&&&&&&&&&&if&((pos&&=&0)&&&&(pos&&=&this.fileendpos)&&&&(this.fileendpos&!=&0))&{&&&&&&&&&&&&&&&&&&&this.buf[(int)(pos&-&this.bufstartpos)]&=&&&&&&&&&&&&&&&}&else&if&(((pos&==&0)&&&&(this.fileendpos&==&0))&||&(pos&==&this.fileendpos&+&1))&{&&&&&&&&&&&&&&&&&&&this.buf[0]&=&&&&&&&&&&&&&&&&&&&this.fileendpos++;&&&&&&&&&&&&&&&&&&this.bufusedsize&=&1;&&&&&&&&&&&&&&}&else&{&&&&&&&&&&&&&&&&&&throw&new&IndexOutOfBoundsException();&&&&&&&&&&&&&&}&&&&&&&&&&&&&&this.bufdirty&=&true;&&&&&&&&&&}&&&&&&&&&&this.curpos&=&&&&&&&&&&&return&true;&&&&&&}&&&&&&&&
至此缓冲写基本实现,逐字节COPY一个12兆的文件,(这里牵涉到读和写,结合缓冲读,用BufferedRandomAccessFile试一下读/写的速度):
耗用时间(秒)
RandomAccessFile
RandomAccessFile
BufferedInputStream + DataInputStream
BufferedOutputStream + DataOutputStream
BufferedRandomAccessFile
BufferedOutputStream + DataOutputStream
BufferedRandomAccessFile
BufferedRandomAccessFile
可见综合读/写速度已超越BufferedInput/OutputStream+DataInput/OutputStream。
优化BufferedRandomAccessFile。
优化原则:
&&& 调用频繁的语句最需要优化,且优化的效果最明显。
&&& 多重嵌套逻辑判断时,最可能出现的判断,应放在最外层。
&&& 减少不必要的NEW。
这里举一典型的例子:
Java代码 &
&public&void&seek(long&pos)&throws&IOException&{&&...&&&&&&&&&this.bufstartpos&=&&pos&*&bufbitlen&/&&&&&&&&&&&&&&&&&&...&&}&&
seek函数使用在各函数中,调用非常频繁,上面加重的这行语句根据pos和bufsize确定buf[]对应当前文件的映射位置,用&*&、&/&确定,显然不是一个好方法。
优化一:this.bufstartpos = (pos && bufbitlen) &&
优化二:this.bufstartpos = pos & // this.bufmask = ~((long)this.bufsize - 1);
两者效率都比原来好,但后者显然更好,因为前者需要两次移位运算、后者只需一次逻辑与运算(bufmask可以预先得出)。
至此优化基本实现,逐字节COPY一个12兆的文件,(这里牵涉到读和写,结合缓冲读,用优化后BufferedRandomAccessFile试一下读/写的速度):
耗用时间(秒)
RandomAccessFile
RandomAccessFile
BufferedInputStream + DataInputStream
BufferedOutputStream + DataOutputStream
BufferedRandomAccessFile
BufferedOutputStream + DataOutputStream
BufferedRandomAccessFile
BufferedRandomAccessFile
BufferedRandomAccessFile优
BufferedRandomAccessFile优
可见优化尽管不明显,还是比未优化前快了一些,也许这种效果在老式机上会更明显。
以上比较的是顺序存取,即使是随机存取,在绝大多数情况下也不止一个BYTE,所以缓冲机制依然有效。而一般的顺序存取类要实现随机存取就不怎么容易了。
需要完善的地方
提供文件追加功能:
Java代码 &
public&boolean&append(byte&bw)&throws&IOException&{&&&&&return&this.write(bw,&this.fileendpos&+&1);&&}&&
提供文件当前位置修改功能:
Java代码 &
public&boolean&write(byte&bw)&throws&IOException&{&&&&&return&this.write(bw,&this.curpos);&&}&&
返回文件长度(由于BUF读写的原因,与原来的RandomAccessFile类有所不同):
Java代码 &
public&long&length()&throws&IOException&{&&&&&return&this.max(this.fileendpos&+&1,&this.initfilelen);&&}&&
返回文件当前指针(由于是通过BUF读写的原因,与原来的RandomAccessFile类有所不同):
Java代码 &
public&long&getFilePointer()&throws&IOException&{&&&&&return&this.&&}&&
提供对当前位置的多个字节的缓冲写功能:
Java代码 &
public&void&write(byte&b[],&int&off,&int&len)&throws&IOException&{&&&&&&&&&&long&writeendpos&=&this.curpos&+&len&-&1;&&&&&&&&&&if&(writeendpos&&=&this.bufendpos)&{&&&&&&&&&&&&&&&System.arraycopy(b,&off,&this.buf,&(int)(this.curpos&-&this.bufstartpos),&len);&&&&&&&&&&&&&&this.bufdirty&=&true;&&&&&&&&&&&&&&this.bufusedsize&=&(int)(writeendpos&-&this.bufstartpos&+&1);&&&&&&&&&&}&else&{&&&&&&&&&&&&&&&super.seek(this.curpos);&&&&&&&&&&&&&&super.write(b,&off,&len);&&&&&&&&&&}&&&&&&&&&&if&(writeendpos&&&this.fileendpos)&&&&&&&&&&&&&&this.fileendpos&=&&&&&&&&&&&this.seek(writeendpos+1);&&}&&public&void&write(byte&b[])&throws&IOException&{&&&&&&&&&&this.write(b,&0,&b.length);&&}&&
提供对当前位置的多个字节的缓冲读功能:
Java代码 &
public&int&read(byte&b[],&int&off,&int&len)&throws&IOException&{&&&&&&long&readendpos&=&this.curpos&+&len&-&1;&&&&&&if&(readendpos&&=&this.bufendpos&&&&readendpos&&=&this.fileendpos&)&{&&&&&&&&&&&System.arraycopy(this.buf,&(int)(this.curpos&-&this.bufstartpos),&b,&off,&len);&&&&&&}&else&{&&&&&&&if&(readendpos&&&this.fileendpos)&{&&&&&&&&&&&len&=&(int)(this.length()&-&this.curpos&+&1);&&&&&&}&&&&&&&&&super.seek(this.curpos);&&&&&&&&&len&=&super.read(b,&off,&len);&&&&&&&&&readendpos&=&this.curpos&+&len&-&1;&&&&&}&&&&&&&&&this.seek(readendpos&+&1);&&&&&&&&&return&&&}&&public&int&read(byte&b[])&throws&IOException&{&&&&&return&this.read(b,&0,&b.length);&&}&&public&void&setLength(long&newLength)&throws&IOException&{&&&&&if&(newLength&&&0)&{&&&&&&&&&this.fileendpos&=&newLength&-&1;&&&&&}&else&{&&&&&&&&&this.fileendpos&=&0;&&&&&}&&&&&super.setLength(newLength);&&}&&&&&&&&public&void&close()&throws&IOException&{&&&&&this.flushbuf();&&&&&super.close();&&}&&
至此完善工作基本完成,试一下新增的多字节读/写功能,通过同时读/写1024个字节,来COPY一个12兆的文件,(这里牵涉到读和写,用完善后BufferedRandomAccessFile试一下读/写的速度):
耗用时间(秒)
RandomAccessFile
RandomAccessFile
BufferedInputStream + DataInputStream
BufferedOutputStream + DataOutputStream
BufferedRandomAccessFile
BufferedOutputStream + DataOutputStream
BufferedRandomAccessFile
BufferedRandomAccessFile
BufferedRandomAccessFile优
BufferedRandomAccessFile优
BufferedRandomAccessFile完
BufferedRandomAccessFile完
与MappedByteBuffer+RandomAccessFile的对比?
JDK1.4+提供了NIO类 ,其中MappedByteBuffer类用于映射缓冲,也可以映射随机文件访问,可见JAVA设计者也看到了RandomAccessFile的问题,并加以改进。怎么通过MappedByteBuffer+RandomAccessFile拷贝文件呢?下面就是测试程序的主要部分:
Java代码 &
RandomAccessFile&rafi&=&new&RandomAccessFile(SrcFile,&&r&);&&RandomAccessFile&rafo&=&new&RandomAccessFile(DesFile,&&rw&);&&FileChannel&fci&=&rafi.getChannel();&&FileChannel&fco&=&rafo.getChannel();&&long&size&=&fci.size();&&MappedByteBuffer&mbbi&=&fci.map(FileChannel.MapMode.READ_ONLY,&0,&size);&&MappedByteBuffer&mbbo&=&fco.map(FileChannel.MapMode.READ_WRITE,&0,&size);&&long&start&=&System.currentTimeMillis();&&for&(int&i&=&0;&i&&&&i++)&{&&&&&&byte&b&=&mbbi.get(i);&&&&&&mbbo.put(i,&b);&&}&&fcin.close();&&fcout.close();&&rafi.close();&&rafo.close();&&System.out.println(&Spend:&&+(double)(System.currentTimeMillis()-start)&/&1000&+&&s&);&&
试一下JDK1.4的映射缓冲读/写功能,逐字节COPY一个12兆的文件,(这里牵涉到读和写):
耗用时间(秒)
RandomAccessFile
RandomAccessFile
BufferedInputStream + DataInputStream
BufferedOutputStream + DataOutputStream
BufferedRandomAccessFile
BufferedOutputStream + DataOutputStream
BufferedRandomAccessFile
BufferedRandomAccessFile
BufferedRandomAccessFile优
BufferedRandomAccessFile优
BufferedRandomAccessFile完
BufferedRandomAccessFile完
MappedByteBuffer+ RandomAccessFile
MappedByteBuffer+ RandomAccessFile
确实不错,看来NIO有了极大的进步。建议采用 MappedByteBuffer+RandomAccessFile的方式。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1682659次
积分:19630
积分:19630
排名:第137名
原创:57篇
转载:1369篇
评论:289条
(1)(10)(1)(4)(3)(14)(27)(17)(5)(34)(24)(17)(25)(43)(8)(24)(1)(10)(1)(2)(2)(12)(1)(5)(12)(13)(9)(1)(5)(107)(21)(35)(2)(4)(11)(21)(3)(8)(2)(4)(3)(12)(6)(4)(9)(20)(10)(39)(24)(2)(59)(32)(34)(13)(44)(150)(56)(50)(41)(24)(95)(34)(3)(8)(43)(35)(27)
<a href="/article

我要回帖

更多关于 java 里面 的文章

 

随机推荐