文件传输基础——Java IO流
一、文件的编码
package com.study.io; /**
* 测试文件编码
*/
public class EncodeDemo { /**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String s="好好学习ABC";
byte[] bytes1=s.getBytes();//这是把字符串转换成字符数组,转换成的字节序列用的是项目默认的编码(这里为UTF-8)
for (byte b : bytes1) {
//把字节(转换成了int)以16进制的方式显示
System.out.print(Integer.toHexString(b & 0xff)+" ");//& 0xff是为了把前面的24个0去掉只留下后八位
}
System.out.println();
/*utf-8编码中中文占用3个字节,英文占用1个字节*/
byte[] bytes2 = s.getBytes("utf-8");//这里会有异常展示,我们就throw这个异常
for (byte b : bytes2) {
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
System.out.println();
/*gbk编码中文占用2个字节,英文占用1个字节*/
byte[] bytes3 = s.getBytes("gbk");//这里会有异常展示,我们就throw这个异常
for (byte b : bytes3) {
System.out.print(Integer.toHexString(b & 0xff)+" ");
} System.out.println();
/*utf-16be编码中文占用2个字节,英文占用2个字节*/
byte[] bytes4 = s.getBytes("utf-16be");//这里会有异常展示,我们就throw这个异常
for (byte b : bytes4) {
System.out.print(Integer.toHexString(b & 0xff)+" ");
} System.out.println();
/*当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码*/
String str1=new String(bytes4);//这时会使用项目默认的编码来转换,可能出现乱码
System.out.println(str1);
//要使用字节序列的编码来进行转换
String str2=new String(bytes4,"utf-16be");
System.out.println(str2);
}
}
分析:
* 1. “& 0xff”的解释:
* 0xFF表示的是16进制(十进制是255),表示为二进制就是“11111111”。
* 那么&符表示的是按位数进行与(同为1的时候返回1,否则返回0)* 2.字节byte与int类型转换:
* Integer.toHexString(b & 0xff)这里先把byte类型的b和0xff进行了运算,然后Integer.toHexString取得了十六进制字符串
* 可以看出b & 0xFF运算后得出的仍然是个int,那么为何要和 0xFF进行与运算呢?直接 Integer.toHexString(b);,将byte强转为int不行吗?答案是不行的.
* 其原因在于:1.byte的大小为8bits而int的大小为32bits;2.java的二进制采用的是补码形式
* Integer.toHexString的参数是int,如果不进行&0xff,那么当一个byte会转换成int时,由于int是32位,而byte只有8位这时会进行补位。。。。。。
* 所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,结果中的高的24个比特就总会被清0,于是结果总是我们想要的。* 3.utf-8编码:中文占用3个字节,英文占用1个字节
* gbk编码:中文占用2个字节,英文占用1个字节
* Java采用双字节编码(就是Java中的一个字符占两个字节)是utf-16be编码。中文占用2个字节,英文占用2个字节
*
* 4.当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码* 5.文本文件 就是字节序列。可以是任意编码的字节序列。
* 如果我们在中文机器上直接创建文本文件,那么该文件只认识ANSI编码(例如直接在电脑中创建文本文件)
二、File类的使用
package com.study.io; import java.io.File; /**
* File类的使用
*/
public class FileDemo {
/*java.iO.File类表示文件或目录
File类只用于表示文件或目录的信息(名称,大小等),不能用于文件内容的访问。*/
public static void main(String[] args) {
File file=new File("D:\\111");//创建文件对象时指定目录需要用双斜杠,因为“\”是转义字符
/*目录的中间的分隔符可以用双斜杠,也可以用反斜杠,也可以用File.separator设置分隔符*/
// File file1=new File("d:"+File.separator);
// System.out.println(file.exists());//exists()判断文件或文件夹是否存在
if(!file.exists()){//如果文件不存在
file.mkdir();//创建文件夹mkdir(),还有mkdirs()创建多级目录
}else{
file.delete();//删除文件或文件夹
}
//判断是否是一个目录isDirectory,如果是目录返回true,如果不是目录或者目录不存在返回false
System.out.println(file.isDirectory());
//判断是否是一个文件isFile
System.out.println(file.isFile()); File file2=new File("D:\\222","123.txt");
//常用API:
System.out.println(file);//打印的是file.toString()的内容
System.out.println(file.getAbsolutePath());//获取绝对路径
System.out.println(file.getName());//获取文件名称
System.out.println(file2.getName());
System.out.println(file.getParent());//获取父级绝对路径
System.out.println(file2.getParentFile().getAbsolutePath());
}
}
运行结果:
说明:
java.iO.File类表示文件或目录
File类只用于表示文件或目录的信息(名称,大小等),不能用于文件内容的访问。
常用的API:
1.创建File对象:File file=new File(String path);注意:File.seperater();获取系统分隔符,如:“\”.
2.boolean file.exists();是否存在.
3.file.mkdir();或者file.mkdirs();创建目录或多级目录。
4.file.isDirectory()判断是否是目录
file.isFile()判断是否是文件。
5.file.delete();删除文件或目录。
6.file.createNewFile();创建新文件。
7.file.getName()获取文件名称或目录绝对路径。
8.file.getAbsolutePath()获取绝对路径。
9.file.getParent();获取父级绝对路径。
❤❤1、遍历目录
package com.study.io; import java.io.File;
import java.io.IOException; /**
* File工具类
* 列出File类的常用操作,比如:过滤、遍历等操作
*/
public class FileUtils {
/**
* 列出指定目录下(包括其子目录)的所有文件
* @param dir
* @throws IOException
*/
public static void listDirectory(File dir) throws IOException{
if(!dir.exists()){//exists()方法用于判断文件或目录是否存在
throw new IllegalArgumentException("目录:"+dir+"不存在");
}
if(!dir.isDirectory()){//isDirectory()方法用于判断File类的对象是否是目录
throw new IllegalArgumentException(dir+"不是目录");
}
/*String[] fileNames = dir.list();//list()方法用于列出当前目录下的子目录和文件(直接是子目录的名称,不包含子目录下的内容),返回的是字符串数组
for (String string : fileNames) {
System.out.println(string);
}*/ //如果要遍历子目录下的内容就需要构造成File对象做递归操作,File提供了直接返回File对象的API
File[] listFiles = dir.listFiles();//返回的是直接子目录(文件)的抽象
if(listFiles !=null && listFiles.length >0){
for (File file : listFiles) {
/*System.out.println(file);*/
if(file.isDirectory()){
//递归
listDirectory(file);
}else{
System.out.println(file);
}
}
}
}
}
测试类:
public class FileUtilsTest1 {
public static void main(String[] args) throws IOException {
FileUtils.listDirectory(new File("D:\\ioStudy"));
}
}
运行结果:
三、RandomAccessFile类的使用
RandomAccessFile:java提供的对文件内容的访问,既可以读文件,也可以写文件。
RandomAccessFile支持随机访问文件,可以访问文件的任意位置。
注意 Java文件的模型:
示例代码:
package com.study.io; import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays; /**
* RandomAccessFile
*/
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException{
File demo = new File("demo");
if(!demo.exists()){
demo.mkdir();
}
File file = new File(demo,"raf.dat");
if(!file.exists()){
file.createNewFile();
} RandomAccessFile raf = new RandomAccessFile(file, "rw");
//指针的位置
System.out.println(raf.getFilePointer()); raf.write('A');//只写了一个字节
System.out.println(raf.getFilePointer());
raf.write('B'); int i = 0x7fffffff;
//用write方法每次只能写一个字节,如果要把i写进去就得写4次
raf.write(i >>> 24);//高8位
raf.write(i >>> 16);
raf.write(i >>> 8);
raf.write(i);
System.out.println(raf.getFilePointer()); //可以直接写一个int
raf.writeInt(i); String s = "中";
byte[] gbk = s.getBytes("gbk");
raf.write(gbk);
System.out.println(raf.length()); //读文件,必须把指针移到头部
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.println(Integer.toHexString(b & 0xff)+" ");
}
raf.close();
}
}
运行结果:
0
1
6
12
[65, 66, 127, -1, -1, -1, 127, -1, -1, -1, -42, -48]
41
42
7f
ff
ff
ff
7f
ff
ff
ff
d6
d0
四、字节流(InputStream、OutputStream)
Java流操作有关的类或接口:
Java流类图结构:
IO流的分类
- 根据处理数据类型的不同分为:字符流和字节流
- 根据数据流向不同分为:输入流和输出流
字符流和字节流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:
- 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
- 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
输入流和输出流
对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。
代码示例:
package com.study.io; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; /**
* IO工具类
* ❤文件输入输出流:
* FileInputStream-->具体实现了在文件上读取数据
* FileOutputStream-->实现了向文件中写出byte数据的方法
* ❤数据输入输出流:
* DataOutputStream / DataInputStream:对"流"功能的扩展,可以更加方面的读取int,long,字符等类型数据
* DataOutputStream writeInt()/writeDouble()/writeUTF()
* ❤字节缓冲流:
* BufferedInputStream & BufferedOutputStream
* 这两个流类位IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能
* 比如:从应用程序中把输入放入文件,相当于将一缸水倒入到另一个缸中:
FileOutputStream--->write()方法相当于一滴一滴地把水“转移”过去
DataOutputStream-->writeXxx()方法会方便一些,相当于一瓢一瓢把水“转移”过去
BufferedOutputStream--->write方法更方便,相当于一瓢一瓢先放入桶中(即缓存区),再从桶中倒入到另一个缸中,性能提高了
*/
public class IOUtil { /**
* 读取指定文件内容,按照16进制输出到控制台
* 并且每输出10个byte换行
* @param fileName
* 单字节读取不适合大文件,大文件效率很低
*/
public static void printHex(String fileName)throws IOException{
//把文件作为字节流进行都操作
FileInputStream in=new FileInputStream(fileName);
int b;
int i=1;
while((b=in.read())!=-1){
/* 0xff换成2进制就是8个1,这样与的话,其实就是取到了字符的低8位。
* oxf就是15, 小于15的数会转换成一个16进制数,
* 你的代码里希望是固定的两个16进制数,所以当只会产生一个时要加个0*/
if(b <= 0xf){
//单位数前面补0
System.out.print("0");
}
//Integer.toHexString(b)将整型b转换为16进制表示的字符串
System.out.print(Integer.toHexString(b)+" ");
if(i++%10==0){
System.out.println();
}
}
in.close();//文件读写完成以后一定要关闭
} /**
* 批量读取,对大文件而言效率高,也是我们最常用的读文件的方式
* @param fileName
* @throws IOException
*/
public static void printHexByByteArray(String fileName)throws IOException{
FileInputStream in = new FileInputStream(fileName);
byte[] buf = new byte[8 * 1024];
/*从in中批量读取字节,放入到buf这个字节数组中,
* 从第0个位置开始放,最多放buf.length个
* 返回的是读到的字节的个数
*/
/*int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大
int j = 1;
for(int i = 0; i < bytes;i++){
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
if(j++%10==0){
System.out.println();
}
}*/
int bytes = 0;
int j = 1;
while((bytes = in.read(buf,0,buf.length))!=-1){
for(int i = 0 ; i < bytes;i++){
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
/**
* & 0xff:byte类型8位,int类型32位,为了避免数据转换错误,通过&0xff将高24位清零
*/
if(j++%10==0){
System.out.println();
}
}
}
in.close();
} /**
* 文件拷贝,字节批量读取
* @param srcFile
* @param destFile
* @throws IOException
*/
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[8 * 1024];//批量读写
int b;
while ((b = in.read(buf, 0, buf.length)) != -1) {//read(buf,0,buf.length)带参数的read返回的是字节的总长度;当全部读完后返回的是-1;
out.write(buf, 0, b);
out.flush();// 最好加上
}
in.close();
out.close();
} /**
* 进行文件的拷贝,利用带缓冲的字节流
* @param srcFile
* @param destFile
* @throws IOException
*/
public static void copyFileByBuffer(File srcFile,File destFile)throws IOException{
if(!srcFile.exists()){
throw new IllegalArgumentException("文件:"+srcFile+"不存在");
}
if(!srcFile.isFile()){
throw new IllegalArgumentException(srcFile+"不是文件");
}
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
int c ;
while((c = bis.read())!=-1){
bos.write(c);
bos.flush();//刷新缓冲区
}
bis.close();
bos.close();
} /**
* 单字节,不带缓冲进行文件拷贝
* @param srcFile
* @param destFile
* @throws IOException
*/
public static void copyFileByByte(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);
int c ;
while((c = in.read())!=-1){//read()不带参数的read返回的是读到的字节内容;当全部读完后返回的都是是-1;
out.write(c);
out.flush();
}
in.close();
out.close();
}
}
测试类:
package com.study.io; import java.io.File;
import java.io.IOException; import org.junit.Test; public class IOUtilTest { @Test
public void testPrintHex() {
try {
IOUtil.printHex("D:\\Javaio\\FileUtils.java");
} catch (IOException e) {
e.printStackTrace();
}
} @Test
public void testPrintHexByByteArray() {
try {
long start = System.currentTimeMillis();//当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫秒为单位测量)
//IOUtil.printHexByByteArray("e:\\javaio\\FileUtils.java");
//IOUtil.printHex("e:\\javaio\\1.mp3");
IOUtil.printHexByByteArray("e:\\javaio\\1.mp3");
System.out.println();
long end = System.currentTimeMillis();
System.out.println(end - start);
} catch (IOException e) {
e.printStackTrace();
}
} @Test
public void testCopyFile(){
try {
IOUtil.copyFile(new File("d:\\javaio\\1.txt"), new File("d:\\javaio\\1copy.txt"));
} catch (IOException e) {
e.printStackTrace();
}
} @Test
public void testCopyFileByBuffer(){
try {
long start = System.currentTimeMillis();
/*IOUtil.copyFileByByte(new File("e:\\javaio\\1.mp3"), new File(
"e:\\javaio\\2.mp3"));*/ //两万多毫秒
/*IOUtil.copyFileByBuffer(new File("e:\\javaio\\1.mp3"), new File(
"e:\\javaio\\3.mp3"));//一万多毫秒*/
IOUtil.copyFile(new File("e:\\javaio\\1.mp3"), new File(
"e:\\javaio\\4.mp3"));//7毫秒
long end = System.currentTimeMillis();
System.out.println(end - start );
} catch (IOException e) {
e.printStackTrace();
}
}
}
五、字符流(Reader、Writer)
package com.study.io; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter; public class IsrAndOswDemo {
public static void main(String[] args)throws IOException {
FileInputStream in = new FileInputStream("e:\\javaio\\utf8.txt");
InputStreamReader isr = new InputStreamReader(in,"utf-8");//默认项目的编码,操作的时候,要写文件本身的编码格式 FileOutputStream out = new FileOutputStream("e:\\javaio\\utf81.txt");
OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
/*int c ;
while((c = isr.read())!=-1){
System.out.print((char)c);
}*/
char[] buffer = new char[8*1024];
int c;
/*批量读取,放入buffer这个字符数组,从第0个位置开始放置,最多放buffer.length个返回的是读到的字符的个数*/
while(( c = isr.read(buffer,0,buffer.length))!=-1){
String s = new String(buffer,0,c);
System.out.print(s);
osw.write(buffer,0,c);
osw.flush();
}
isr.close();
osw.close(); } }
❤ 字符流之文件读写流(FileReader/FileWriter)
❤ 字符流的过滤器
六、对象的序列化和反序列化
示例:
注意:
序列化拓展文章:
文件传输基础——Java IO流的更多相关文章
- 慕课网_文件传输基础——Java IO流
第1章 文件的编码 1-1 文件的编码 (15:07) 第2章 File 类的使用 2-1 File 类常用 API 介绍 (10:50) import java.io.File; import ja ...
- 文件传输基础----Java IO流
编码问题 一个很著名的奇怪现象:当你在 windows 的记事本里新建一个文件,输入"联通"两个字之后,保存,关闭,然后再次打开,你会发现这两个字已经消失了,代之的是几个乱码!呵呵 ...
- Java IO流详解(二)——File类
在上一章博客中简单的介绍了Java IO流的一些特征.也就是对文件的输入输出,既然至始至终都离不开文件,所以Java IO流的使用得从File这个类讲起. File类的描述:File类是文件和目录路径 ...
- Java:IO流与文件基础
Java:IO流与文件基础 说明: 本章内容将会持续更新,大家可以关注一下并给我提供建议,谢谢啦. 走进流 什么是流 流:从源到目的地的字节的有序序列. 在Java中,可以从其中读取一个字节序列的对象 ...
- 【Java基础】Java IO流的总结
Java IO流分为输入流和输出流,而输入流和输出流中又分字符流和字节流.顾名思义,输入流则是输入到程序中计算,输出流是把程序的结果输出到文件或者设备.而字符流输入输出以字符为单位,字节流则是以字节为 ...
- java基础之 IO流
javaIO流 IO流 : (input output) 输入输出流 :输入 :将文件读到内存中 输出:将文件从内存输出到其他地方. IO技术的作用:主要就是解决设备和设备之间的数据传输问题 ...
- java基础06 IO流
IO用于在设备间进行数据传输的操作. Java IO流类图结构: IO流分类 字节流: InputStream FileInputStream BufferedInputStream Output ...
- Java基础之IO流学习总结
Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...
- java基础之io流总结一:io流概述
IO流概念: 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.io流是实现输入和输出的基础,可以方便的实现数据的输入和输出操作. IO流的分类: 根据处理数据类型的不同分为:字符流 ...
随机推荐
- 7. Add a networking service
Controller Node: 1. sudo vi /etc/nova/nova.conf [DEFAULT] ... network_api_class = nova.network.api.A ...
- 如何使用 Migration创建一个迁移
切换到YII所在的目录 yii migrate/create test
- windows服务器。linux服务器的集成包推荐
我对linux不熟悉,这个有点不好意思,虽然我是做php开发的.我只是对apache+php+mysql的操作熟悉而已,但是linux的服务器配置什么的都太懂 所以我就安装了windows2008,安 ...
- ci调用application/views下的css,js,图片资源出现You don't have permission to access CodeIgniter on this server解决
原因是view文件下面有个.htaccess文件,里面写的是 Deny from all //拒绝所有请求 自己本地测试的话,就直接去掉,放到服务器就指定application/views文件 ...
- JAVA图片相关
有些图片后缀为jpg,但是实际格式却不是jpg,通过url下载图片字节.然后用ImageIO读取时,出现返回null的情况.出现这种情况,就需要使用webp-imageio.jar.(https:// ...
- [办公自动化]利用Acrobat完成问卷调查或者考试卷
整体思路:(软件环境Acrobat) 1.制作问卷. 采用word制作,制作基础页面,然后倒入.自己亲测时,发现一般的文字域是可以的,但是单选按钮就不能导入. 如果是考试卷,可以利用word制作基础页 ...
- mysql查询所有字段(*),并且联表时需要特别注意的地方
如果不标明*是读取哪个表,确实会将所有三个表都读出来.需要小心
- qTip2 精致的jQuery提示信息插件
qTip2 精致的jQuery提示信息插件 出处:http://www.cnblogs.com/lwme/archive/2012/02/16/qtip2-jquery-plugin.html ...
- MVC3中几个小知识点
1.ViewBag.Name~ViewBag.name等价,即不区分大小写.在此小心,下次见到不要奇怪,不过最好还是写成一样的比较好. 2.JS字符串不允许有换行符,\'等字符,需提前处理.
- nrf51822-使用16位自定义UUID
以 ble_app_uart为例 工程中创建的nus服务以及其中的两个特性值都是128位的UUID.nordic sdk中使用128位UUID的方式和标准128UUID类似,它是提供一个基准UUID, ...