首先看一下常用的几种编码方式
public class EncodeDemo
{
public static void main(String[] agrs)throws IOException
{
String s="中国ABC";
byte[] byte1=s.getBytes(); //默认采用项目的UTF-8编码
byte[] byte2=s.getBytes("GBK");//显示指定编码方式为GBK
byte[] byte3=s.getBytes("UTF-16be");
for(byte b:byte1)
{
/**
* 把字节转换成int以十六进制的方式显示
* 默认采用项目的编码,此处使用UTF-8,得到的结果为e4 b8 ad e5 9b bd 41 42 43
*可见采用utf-8编码,中文占用三个字节,英文占用一个字节
*/
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
System.out.println();
for(byte b:byte2)
{
/**
* 把字节转换成int以十六进制的方式显示,高位三个字节补0
* 显示指定编码方式为GBK,,得到的结果为d6 d0 b9 fa 41 42 43
* 可见采用GBK编码,中文占用三个字节,英文占用一个字节
*/
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
System.out.println();
for(byte b:byte3)
{
/**
* java是双字节编码utf-16be
* 把字节转换成int以十六进制的方式显示,高位三个字节补0
* 显示指定编码方式为UTF-16be,得到的结果为4e 2d 56 fd 0 41 0 42 0 43
* 可见采用UTF-16be编码,中文占用两个字节,英文也占用两个字节
*/
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
System.out.println();
/*
* 字节数组转换成字符串,必须与之前的转换采用相同的编码方式,不然会出现乱码
*/
String s1 = new String(byte1);
System.out.println(s1); //中国ABC,采用默认的项目编码格式
String s2 = new String(byte2);
System.out.println(s2);//�й� 出现乱码,因为byte2用的是GBK编码,转换成字符串时用得默认的UTF-8
String s3 = new String(byte2,"GBK");
System.out.println(s3);//中国ABC ,显示指定GBK编码方式,便不会出现乱码
}
}
通过这个例子可以看出,常用的编码方式有UTF-8,汉字编码站三个字节,英文字母编码占用1个字节; GBK编码,中文占用两个字节,英文字母占用一个字节;java 是双字节UTF-16be编码,这种编码方式中文和英文都占用两个字节,在字符串与字节进行转换时,默认采用项目指定的编码方式,还要注意双向转换时,编码方式要相同,不然会出现乱码。
File类的使用:
java.io.File类用于表示文件或目录,它只用于表示文件或目录的信息(名称,大小等),不能用于文件内容的访问
public class FileDemo {
public static void main(String[] args)
{
/*
* 了解几种常用的构造函数
*/
File file = new File("F:\\开心");//注意:路径要使用双斜杠或者反斜杠
System.out.println(file);
File file2 = new File("F:\\开心","开心1.txt");
File file3 = new File(file2,"开心2.txt");
if(!file.exists())
{
/*
* 如果目录不存在,则创建目录,mkdirs()可用于创建多级目录
* file.createNewFile()用于创建文件
*/
file.mkdir();
}
else
{
file.delete();
}
/*
* File类的几种常用API
*/
System.out.println(file.isFile());
System.out.println(file.isDirectory());
System.out.println(file); //打印文件的路径
System.out.println(file.getAbsolutePath());//同样打印文件的完整路径
System.out.println(file.getName());//打印文件或目录的名字
System.out.println(file.getParent());//打印文件或目录的父目录
System.out.println(file.getParentFile());
}
}
以上介绍FIle类创建对象的几种方式以及常用API
包装对对文件或目录的几种常用操作,如过滤,遍历等
/<span style="font-family: Arial, Helvetica, sans-serif;">/包装File的一些常用操作,如过滤,遍历</span>
public class FileUtil
{
/*
* 遍历目录下的所有文件和目录
*/
public static void listDirectory(File dir)throws IOException
{
if(!dir.exists())
{
throw new IllegalArgumentException("目录"+dir+"不存在");
}
if(!dir.isDirectory())
{
throw new IllegalArgumentException(dir+"不是目录");
}
/*
String[] fileNames = dir.list(); //返回字符串数组,直接子的名称,不包含子目录下的内容
for (String string : fileNames)
{
System.out.println(string);
}*/
File[] files = dir.listFiles();
if(files!=null && files.length>0)
{
for (File file : files)
{
System.out.println(file);
if(file.isDirectory()) //递归遍历
{
listDirectory(file);
}
}
}
}
}
RandomAccessFile类:提供了对文件内容的访问,既可以读文件,也可以写文件。它提供对文件的随机访问,可以访问文件的任意位置
1>文件模式
java文件,在硬盘上是byte byte byte...存储的,是数据的集合
2>打开文件
打开文件有两种模式 “rw” 读写操作 “r” 只读操作
RandomAccessFile raf = new RandomAccessFile (file , "wr"),RandomAccessFile的随机访问是依靠文件指针实现的,打开文 件的默认指针位置prointer=0,即在文件的开头。读写操作会伴随着指针位置的移动。
3>写方法
raf.write(int), ----->只写一个字节,同时指针只想下一个位置,准备再次进行写操作
4>读方法
raf.read()---->只写一个字节
5>文件读写完成后一定要关闭,不然会发生意想不到的错误
public class RandomAccessFileDemo {
public static void main(String[] args)throws IOException
{
File file = new File("demo");
if(!file.exists())
{
file.createNewFile();
}
RandomAccessFile raf = new RandomAccessFile(file, "rw");
System.out.println(raf.getFilePointer()); //获取文件指针的位置,0
raf.write('A');//只写入一个字节
System.out.println(raf.getFilePointer()); //1
int i = 0x7fffffff;//最大的整数
//用write方法,每次只能写一个字节,写一个int需要写4次
raf.write(i>>24);
raf.write(i>>16);
raf.write(i>>8);
raf.write(i);
//也可以直接写一个int,时机底层也是进行四次写操作
raf.writeInt(i);
System.out.println(raf.getFilePointer());
String s="中国";
byte[] byte1 = s.getBytes("gbk");
raf.write(byte1);
System.out.println(raf.length()); //文件的长度 13
//读文件必须把文件指针移到文件的开始,也可以移到指定的位置进行读取
raf.seek(0);
byte[] buf = new byte[(int) raf.length()];
raf.read(buf) ;//批量读取
System.out.println(Arrays.toString(buf));
//以十六进制的方式输出
for (byte b : buf)
{
System.out.print(Integer.toHexString(b&0xff)+" ");
}
raf.close();
}
}
I O流(输入流,输出流)
字节流:
1>
InputStream 抽象了应用程序读取数据的方式,读到程序中为输入
OutputStream 抽象了应用程序写出数据的方式
2>
EOF =End 读到-1就读到了文件的结尾
3>输入流基本方法
int b = in.read(); 读取一个字节填充到int低八位
in.read(byte[] buf) ; 批量读取字节到字节数组中
in.read(byte[] buf , int start ,int size)
4>输出流基本方法
out.write(int b) // 写出int b 的低八位到流
out.write(byte[] b) ; 写出字节数组中的全部字节
out.write(byte[] b , int start ,int size) //从下表start开始,写出size个字节
5>具体实现类
FileInputStream --->具体实现了在文件中读取数据
/*
* 读取指定文件内容,以十六进制输出到控制台
* 每读取10个字节换行,
* 单字节读取,不适合大文件,效率很低
*/
public class IOUtil
{
public static void printHex(String filename)throws IOException
{
FileInputStream fis = new FileInputStream(filename);
int b;
int i=1;
while((b=fis.read())!=-1) //每次只读取一个字节
{
if(b<=0xf)
System.out.print("0"); //如果只有第四位,则在前面补零
System.out.print(Integer.toHexString(b)+" ");
if(i++%10 == 0)
{
System.out.println();
}
}
fis.close();
}
/*
* 批量读取,大区大文件时效率很高
* 常用的文件读取方式
*/
public static void printHexByByteArray(String filename)throws IOException
{
FileInputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[10*1024];
/*
* 从fis中批量读取字节,放入到buf中,从第0个位置开始放,最多放buffer.length个字节
* 返回的是读取字节的个数
* 为了防止一次读不完一个文件,所以用到while循环,读到文件结尾为止
*/
int n;
while((n=fis.read(buffer, 0, buffer.length))!=-1)
{
int k=1;
for (int i=0;i<n;i++)
{
if(buffer[i]<=0xf)
System.out.print("0");
System.out.print(Integer.toHexString(buffer[i]&0xff)+" ");
if(k++%10 == 0)
System.out.println();
}
}
System.out.println();
fis.close();
}
/*
* 文件的copy
*/
public static void copyFile(File srcFile,File destFile)throws IOException
{
if(!srcFile.exists())
throw new IllegalArgumentException("原文件"+srcFile+"不存在");
if(!srcFile.isFile())
throw new IllegalArgumentException(srcFile+"不是文件");
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(destFile);
byte[] buf = new byte[10*1024];
int n;
while((n=in.read(buf, 0, buf.length))!=-1)
{
out.write(buf, 0, n);
}
}
FileOutputStream --->继承了OutputStream,具体实现了向文件中写入byte数据的方法
public class FileOutputStreamDemo1 {
public static void main(String[] args)throws IOException
{
//如果文件不存在,则创建该文件,如果该文件存在,则删除后再重新创建
FileOutputStream fos = new FileOutputStream("demo.dat",true);
/*
* 如果文件不存在,则创建该文件,如果文件存在,则以追加的方式向文件中写数据
* FileOutputStream fos = new FileOutputStream("demo.dat","true");
*/
fos.write('A'); //写一个字节
String s = "中国";
byte[] b = s.getBytes();
fos.write(b); //写一个字节数组
fos.close();
}
public static void copyFile(File srcFile,File destFile)throws IOException
{
if(!srcFile.exists())
throw new IllegalArgumentException("原文件"+srcFile+"不存在");
if(!srcFile.isFile())
throw new IllegalArgumentException(srcFile+"不是文件");
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(destFile);
byte[] buf = new byte[10*1024];
int n;
while((n=in.read(buf, 0, buf.length))!=-1)
{
out.write(buf, 0, n);
}
}
}
DataInputStrean 和 DataOutputStrean 采用装饰模式,底层包装一个字节的读取操作
out.writeInt(10);
out.writeInt(-10);
out.writeLong(10l);
out.writeDouble(1.11);
out.writeUTF("中国");
out.writeChars("中国人");
DataInputStrean中有与之对应的read操作
带缓冲的字节流
BufferedInputStream 和BufferedOutputStream,为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式,提高了IO的性能
public static void copyFileBuffer(File srcFile,File destFile)throws IOException
{
if(!srcFile.exists())
throw new IllegalArgumentException("原文件"+srcFile+"不存在");
if(!srcFile.isFile())
throw new IllegalArgumentException(srcFile+"不是文件");
BufferedInputStream in = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(destFile));
int n;
while((n=in.read())!=-1)
{
out.write(n);
out.flush();//必须写
}
in.close();
out.close();
}
还可以自己写一个copyFileByByte(),经过比较,在进行较大的文件的copy工作时,自己创建byte[] 数组批量读取时,速度最快,带缓冲区的方式次之,当然可以想到,单个字节拷贝方式最慢。
字符流
1>认识文本和文本文件
java文本(char) 是16位无符号整数,是字符的Unicode编码(双字节编码)
文件是byte byte byte 。。 的序列集合文本文件是文本按照一定的编码方式序列化为byte的存储方式
2>字符流(Reader Writer)
字符流的底层仍然是基本的字节序列
字符流的基本实现 ---->操作文本文本文件
InputStreamReader -->完成byte流 解析为 char流 ,按照编码解析
OutputStreamWrite -->完成char流到byte流的解析,同样按照编码解析
public class FIRandFOW
{
public static void main(String[] args)throws IOException
{
FileInputStream in = new FileInputStream("C:\\unintall.log");
/*
* 可以指定编码方式,自动识别换行
*/
InputStreamReader reader = new InputStreamReader(in,"GBk");
FileOutputStream out = new FileOutputStream("C:\\unintall1.log");
OutputStreamWriter writer = new OutputStreamWriter(out,"GBk");
int a;
/* 单个字符读取
while((a = reader.read())!=-1)
{
System.out.print((char)a);
}*/
//批量读取
char[] buffer = new char[8*1024];
while((a=reader.read(buffer,0,buffer.length))!=-1)
{
writer.write(buffer, 0, a);
writer.flush();//要加上刷新,才能及时将字符数组中的内容输出到文件
String s = new String(buffer,0,a);
System.out.println(s);
}
}
}
FileReader 和 FileWriter
同 InputStreamReader 和 OutputStreamWriter读取字符和字符数组方式一样,只是创建对象的方式不同
DataInputStrean
FileReader read = new FileReader(file);
FileWriter write = new FileWriter(file); 构造函数的参数是File对象
注:这种字符流操作存在一些缺陷,我们看到在构造方法中没办法指定编码方式,所以,读取文件的编码必须和文件的编码相同,不然会出现乱码
字符流的过滤器
BufferedReader 和 BufferedWriter PrintWriter
优点是能以行为单位进行文件的读取
public class BufferReaderWriter
{
public static void main(String[] args) throws IOException
{
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream("C:\\unintall.log"),"GBK"));
//BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\unintall1.log")));
PrintWriter pwriter = new PrintWriter("C:\\unintall1.log");
String line;
/*
while((line = reader.readLine()) != null)
{
writer.write(line);//不识别换行
writer.newLine();//手动换行
writer.flush();
System.out.println(line);
}*/
/*
* 由于BufferedWriter创建对象比较复杂,并且不识别换行,所以用PrintWriter替代
*/
while((line = reader.readLine()) != null)
{
pwriter.println(line); //用该方法进行换行
pwriter.flush();
System.out.println(line);
}
}
}
以上就是javaIO的基本类以及常用的操作,我们完全可以参照这篇文章对API中的其他IO类进行扩展学习