Java基础(20,21)IO流
2015-04-06 10:45
381 查看
二十八.IO流列出目录下所有内容-递归
import java.io.*; class IoTextDemo { public static void main(String[] args) { //开始名字写错了,返回null File dir = new File("E:\\JAVA_TEXT"); //System.out.println(dir);//打印的是E:\\JAVA_TEST //System.out.println(dir); showDir(dir,0); } public static String getLevel(int level) { StringBuilder sb = new StringBuilder(); sb.append("|--"); for(int i = 0;i<level;i++) { sb.insert(0 ,"| "); } return sb.toString(); } public static void showDir(File dir,int level) { System.out.println(getLevel(level)+dir.getName()); level++; File[] filelist =dir.listFiles(); //System.out.println(dir);//显示主目录的名字 for(int i = 0;i<filelist.length;i++) { if(filelist[i].isDirectory())//如果读到的是一个目录,就继续往里面读 { showDir(filelist[i],level); } else //不是目录是文件 { System.out.println(filelist[i]);//这个地方不写层级, //只有目录会有| ,文件前面没有 //System.out.println(getLevel(level)+filelist[i]); } } } }
二十九.IO流删除带内容的目录
删除原理:在window中,删除目录从里面往外删除的。
既然从里往外删除。就需要用到递归
import java.io.*; class IoTextDemo { public static void main(String[] args) { File dir = new File("E:\\JAVA_TEXT"); removeDir(dir); } public static void removeDir(File dir) { File[] files = dir.listFiles(); for(int i = 0;i<files.length;i++) { if(files[i].isDirectory()) { removeDir(files[i]);//如果是目录继续往里走,看看是不是目录,知道找到文件然后删除 } else { //如果打印false ,就说明一个文件夹被删了两次 System.out.println(files[i].toString()+"-file-"+files[i].delete()); } } System.out.println(dir+"::"+dir.delete());//删除文件 } }
三十.IO流创建java文件列表, 前面有一个用listFile做的,可以对比一下
练习将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。
建立一个Java文件列表文件。
思路:
1.对指定的目录进行递归。
2.获取递归过程所有的java文件的路径
3.将这些路径存储到集合中,存入list!!!!
4.将集合中的数据写入到一个文件中
import java.io.*; import java.util.*; class IoTextDemo { public static void main(String[] args) { File dir = new File("E:\\JAVA_TEXT"); //FileWriter fw = new FileWriter("E:\\list_document.txt"); File f = new File("E:\\list_java.txt");//看看f打印什么 File f1 = new File("E:\\玩玩.txt"); try { System.out.println(f); //打印出E:\list_java.txt //这个文件存在 System.out.println(f1); //打印出E:\玩玩.txt //这个文件并不存在 } catch (Throwable e) { throw new RuntimeException("cuo"); } ArrayList<File> alist = new ArrayList<File>(); fileAddToList(dir,alist); //把文件信息存到集合中 writeTofile(alist ,f.toString()); //从集合中把信息写到文件上 } public static void fileAddToList(File dir ,ArrayList<File> list ) { File[] files = dir.listFiles(); // 高级for循环取数据 // for(File file : files) // { // if(file.isDirectory()) // { // fileToList(file ,list); // } // else // { // if(file.getName().endsWith(“.java”)) // list.add(file); // } // } //传统for循环 for(int i = 0;i<files.length;i++) { if(files[i].isDirectory()) //如果是目录就继续进去 { fileAddToList(files[i],list) ; } else //如果是文件就添加进list集合 { if(files[i].getName().endsWith("java")) list.add(files[i]); } } } public static void writeTofile(ArrayList<File> list , String file) { FileWriter fw = null; BufferedWriter bufw = null; try { fw = new FileWriter(file); bufw = new BufferedWriter(fw); // 高级for循环取出数据 // for(File f:list) // { // String path = f.getAbsolutePath(); // bufw.write(path); // bufw.newLine(); // bufw.flush(); // } //用迭代器取出数据 Iterator<File> it = list.iterator(); //这里开始写错了 while(it.hasNext()) { File fi = it.next(); String filepath = fi.getAbsolutePath(); bufw.write(filepath); bufw.newLine(); bufw.flush(); } } catch (Throwable e) { throw new RuntimeException("错误1"); } finally { try { if(bufw !=null) { bufw.close(); } } catch (Throwable e) { throw new RuntimeException("错误2"); } } } }
三十一.IO流Properties
//properties是hashtable的子类//也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。
//是集合中和IO技术相结合的结合容器。
//该对象的特点:可以用于键值对形式的配置文件。
//那么在加载数据时,需要数据有固定的格式,通常键 = 值。
import java.io.*; import java.util.*; class IoTextDemo { public static void main(String[] args) throws IOException { //setAndGet(); method_1(); } public static void setAndGet() { Properties prop = new Properties(); //setProperty(String key, String value),调用Hashtable的put方法 prop.setProperty("zhangsan","30"); prop.setProperty("lisi","39"); System.out.println(prop); //stringPropertyNames()返回此属性列表中的键集, //其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键, //则还包括默认属性列表中不同的键。 String value = prop.getProperty("lisi"); System.out.println(value); Set<String> names = prop.stringPropertyNames(); prop.setProperty("lisi",89+"");//改变元素的值//改变值 for(String s : names) { System.out.println(s+":"+prop.getProperty(s)); //获取key } } //代码2 //演示,如何将流中的数据存储到集合中。 //想要将info.txt中键值数据存到集合中进行操作。 //1.用一个流和info.txt文件关联。 //2.读取一行数据,将该行数据用”=”进行切割。 //3.等号左边作为键,右边作为值。存入到Properties集合中即可。 public static void method_1() throws IOException { BufferedReader bufr = new BufferedReader(new FileReader("E:\\SYSTEM_INFO.txt")); String line = null; Properties prop = new Properties(); while((line = bufr.readLine()) != null) { String[] arr = line.split("="); System.out.println(arr[0]+"---"+arr[1]); prop.setProperty(arr[0],arr[1]); } bufr.close(); System.out.println(prop); } ///代码3(优化代码2) public static void loadDemo() throws IOException //跟下面的功能一样,只是更简单了 { Properties prop = new Properties(); FileInputStream fis = new FileInputStream(“info.txt”); //将流中的数据加载进集合。从输入流中读取属性列表(键和元素对)。 prop.load(fis); //System.out.println(prop);//和下面的效果一样 把键和值成对打印 //prop.list(System.out);//和上面的效果一样 //之前是99,这里改成39,打印出39,但是文件中还是99 prop.setProperty(“wangwu”,”39”); / /只是改变了内存中值,源头没改变,如果要改变需要存起来 //store是将内存中的数据(也就是上面的setProperty的数据)先存到流中,然后存到文件中,会打印时间 FileOutputStream fos = new FileOutputStream(“info.txt”); prop.store(fos.”haha”);//haha是注释 fos.close(); fis.close(); } }
三十二.IO流Properties练习
//用于记录应用程序运行次数。//如果使用次数已到,那么给出注册提示。
//很容易想到的是:计数器
//可是该计数器定义在程序中,随着程序的运行而在内存中存在,并自行自增
//可是随着该应用程序的退出,该计数器也在内存中消失了。
//下一次在启动该程序,又重新开始从0计数。
//这样不是我们想要的。
//程序即时结束,该计数器的值也存在。
//下次程序启动时会先加载该计数器的值并加1后再重新存储起来。
//所以要建立一个配置文件。用于记录该软件的使用次数。
//该配置文件使用键值对的形式。
//这样便于阅读数据,并操作数据。
//键值对数据是map集合
//数据是以文件形式存储,使用io技术
//那么map+io-->properties
//配置文件可以实现应用程序数据的共享
import java.io.*; import java.util.*; class IoTextDemo { public static void main(String[] args) throws IOException { File file = new File("E:\\count.txt"); Properties pro = new Properties(); if(!file.exists()) { file.createNewFile(); //如果不存在就创建一个 } FileInputStream fis = new FileInputStream(file); pro.load(fis); int count = 0; String value = pro.getProperty("time"); if(value == null) { count++; pro.setProperty("time",count+""); } else { count = Integer.parseInt(value); //如果没有这个,那么count每次进来都是0!!! count ++; pro.setProperty("time",count+""); if(count >4) { System.out.println("到期,请续费"); } } FileOutputStream fos = new FileOutputStream(file); //改变了数据就要存到file文件中 pro.store(fos,""); fos.close(); fis.close(); } }
三十三.IO流printWriter
PrintWriter与PrintStream可以直接操作输入流和文件
打印流:
该流提供了打印方法,可以将各种数据类型的数据都原样打印!!!
字节打印流:
PrintStream
构造函数可以接受的参数类型:
1.file对象。File
2.字符串路径。String
3.字节输出流。OutputStream(控制台对应的对象时是字节输出流)
字符打印流:
PrintWriter
构造函数可以接受的参数类型:
1file对象。File
2字符串路径。String
3字节输出流。OutputStream
4.字符输出流,Writer (跟上面的差别所在)
PrintWriter(OutputStream out , boolean auto Flush)
out - 输出流
autoFlush - boolean变量;如果为true ,则println,printf或format方法将刷新输出缓冲区
import java.io.*; class IoTextDemo { public static void main(String[] args) throws IOException { BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); //控制台输出 //PrintWriter out = new PrintWriter(System.out , true); //如果把输出写入一个文件时,不能写true,因为针对的是流,才能自动刷新 //PrintWriter out = new PrintWriter("E:\\20150405text2.txt"); //把写入文件也弄成自动刷新 //和上面的区别在于,输入完之后,不用over,文件就自动生成大写 PrintWriter out = new PrintWriter(new FileWriter("E:\\20150405text4.txt"),true); String line = null; while((line = bufr.readLine()) != null) { if("over".equals(line)) { break; } //如果new PrintWriter(System.out , true);不写true,那么输入小写之后不会立即显示写,因为在缓冲区中 //没有刷新,over之后才会全部出来。如果有true,写一个对应的大写就出来了,自动刷新 out.println(line.toUpperCase()); } out.close(); bufr.close(); } }
三十四.IO合并流
//把三个流放一起,然后再写在一个文件里(分别读取三个文件存到一个,要考虑续写问题,多个源对应一个目的)//这里直接把多个源,变成一个源
import java.io.*; import java.util.*; class IoTextDemo { public static void main(String[] args) throws IOException { Vector<FileInputStream> v = new Vector<FileInputStream>(); v.add(new FileInputStream("E:\\hebing\\1.txt")); v.add(new FileInputStream("E:\\hebing\\2.txt")); v.add(new FileInputStream("E:\\hebing\\3.txt")); Enumeration<FileInputStream> en = v.elements(); //SequenceInputStream(Enumeration<? extends InputStream> e) //通过记住参数来初始化新创建的 SequenceInputStream, //该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。 SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("E:\\hebing\\4.txt"); byte[] buf = new byte[1024]; int len = 0; //read(char[] cbuf) //public int read(byte[] b) //从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 //在某些输入可用之前,此方法将阻塞。 while((len = sis.read(buf)) != -1) { fos.write(buf,0,len); } fos.close(); sis.close(); } }
三十五.IO流切割文件
import java.io.*; import java.util.*; class IoTextDemo { public static void main(String[] args)throws IOException { //splitdocu(); sequenceInput(); } public static void splitdocu() throws IOException { FileInputStream fis = new FileInputStream("E:\\hebing\\w.jpeg"); FileOutputStream fos = null; byte[] buf = new byte[1024*15]; int len = 0; int count = 0; while((len = fis.read(buf)) != -1) { count++; fos = new FileOutputStream("E:\\hebing\\"+count+".jpeg"); fos.write(buf,0,len); } fis.close(); fos.close(); } public static void sequenceInput()throws IOException { ArrayList<FileInputStream> list = new ArrayList<FileInputStream>(); for(int i = 1;i<4;i++) { list.add(new FileInputStream("E:\\hebing\\"+i+".jpeg")); //会报错,FileInputStream 无法转为String } final Iterator<FileInputStream> it = list.iterator(); //为什么要这么写,这个真不明白,因为只有Iterator有hasNext和next,Iterator跟Enumeration功能是一样的 //方法摘要 // boolean hasMoreElements()测试此枚举是否包含更多的元素 // E nextElement()如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。 Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() { public boolean hasMoreElements() { return it.hasNext(); } public FileInputStream nextElement() { return it.next(); } }; SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("E:\\hebing\\f.jpeg"); int len = 0; byte[] buf = new byte[1024]; while((len = sis.read(buf)) != -1) { fos.write(buf,0,len); } fos.close(); sis.close(); } }
三十六.IO包中其他类
打印流PrintWriter与PrintStream
可以直接操作输入流和文件
序列流
SequenceInputStream
对多个流进行合并
操作对象 ,也就把堆内存中的对象存到文件中去,这个是他的重点!!!!!(硬盘),ObjectInputStream 与ObjectOutStream,被操作的对象需要实现Serializable(标记接口)
ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream
一起使用时,可以为应用程序提供对对象图形的持久存储(即把对象存到文件中),ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。
import java.io.*; class IoTextDemo { public static void main(String[] args) throws Exception { ///writeObj(); readObj(); } public static void readObj() throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\hebing\\obj.txt")); Person p = (Person)ois.readObject(); System.out.println(p); ois.close(); } public static void writeObj() throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\hebing\\obj.txt")); //oos.writeObject(new Person("lisi",39)); //按理说new person(“lisi”,39)是应该在堆内存当中,这里就都存在对象当中, //想把对象写在硬盘上(文件中)(用方法writeObject) oos.writeObject(new Person("lisi",39,"kr"));//lisi:39:cn//只能把堆里面的序列化, //不能把方法区里面的序列化 oos.close(); } }
三十七.IO流RandomAccessFile
RandomAccessFile,该类不算是IO体系种子类,而是直接继承自Object。但是它是IO包中成员。因为它具备读和写功能,内部封装一个数组,而且通过指针对数组的元素进行操作,可以通过getFilePointer获取指针位置。
同时可以通过seek改变指针的位置
其实完成读写的原理就是内部封装了字节输入流和输出流。
通过构造函数可以看出,该类只能操作文件。
而且操作文件还有模式,只读R,读写rw等。
如果模式为只读r,不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现异常(R),而且该对象的构造函数要操作的文件不存在,会自动创建,如果存在则不会覆盖(W)
RandomAccessFile,随机访问文件,自身具备读写的方法。通过skipBytes(int x),seek(int x)来达到随机访问。!!!!!这个是他的优点.
import java.io.*; class IoTextDemo { public static void main(String[] args) throws Exception { //writeFile(); //readFile(); writeFile_2(); } public static void writeFile() throws IOException { RandomAccessFile raf = new RandomAccessFile("E:\\hebing\\ran1.txt","rw"); raf.write("王五".getBytes());//一个中文2个字节 //raf.write(97);//raf.write只写最低8位,如果超过就不能正确打印比如258, //但是可以用WriteInt(); //文件中是王五a,读四个字节//因为记事本回去查GBK raf.writeInt(97);//文件中是王五 a,中间有3个空格!!!(不是空格,应该是换行符,如果是空格,我自己写的三个空格,等会读年龄的时候读不出来) raf.write("赵四".getBytes()); raf.writeInt(22); raf.close(); } public static void readFile() throws IOException { RandomAccessFile raf = new RandomAccessFile("E:\\hebing\\ran1.txt","r"); //之前打印 //name=王五 //age=97 //调整对象中指针 前后都可以 //raf.skipBytes(8); //跟下面效果一样,只是只能往前走不能往后走!!!!! raf.seek(8);//相当于从第八个字节开始读 一个中文2个字节,int四个字节 //现在打印 //name=赵四 //age=22 byte[] buf =new byte[4]; raf.read(buf); String name = new String(buf); int age = raf.readInt(); System.out.println("name="+name); System.out.println("age="+age); raf.close(); } //可以中间不写,直接写第四个,,或者修改之前写过的,在平常下载的时候, //每一段数据都是单独一个线程进行写,这样就要求数据有规律,比如录入户口,16个字节写名字,四个字节写年龄 //20个字节是一个人,所以这样就可以分段读写 //如果是一般流,只能从头写到尾,只是多个线程从头写到位,那么数据不是按顺序来的, //解码会报错(如下图) public static void writeFile_2()throws IOException { RandomAccessFile raf = new RandomAccessFile("E:\\hebing\\ran1.txt","rw"); raf.seek(8*5);//从第四十个字节开始写 raf.write("周期".getBytes()); raf.writeInt(103); raf.close(); } }
三十八.IO流中的管道流
管道流PopedinputStream 和PipedOutStream
输入输出可以直接进行连接,通过结合教程使用。
管道输入流应该连接到管道输出流;
管道输入流提供要写入管道输出流的所有数据字节。通常,
数据由某个线程从 PipedInputStream 对象读取,
并由其他线程将其写入到相应的 PipedOutputStream。
不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。
import java.io.*; class IoTextDemo { public static void main(String[] args) throws IOException { PipedInputStream in = new PipedInputStream(); PipedOutputStream out = new PipedOutputStream (); in.connect(out); Read r = new Read(in); Write w = new Write(out); new Thread(r).start(); new Thread(w).start(); } } class Read implements Runnable { private PipedInputStream in; Read(PipedInputStream in) { this.in = in; } public void run() { try { System.out.println("读取钱。。。没有数据就阻塞"); byte[] buf = new byte[1024]; int len = in.read(buf);// //阻塞式方法读取数据(如果没有数据就停在这,这时候其他线程就获取执行权) System.out.println("读到数据,阻塞结束"); String s = new String(buf,0,len); System.out.println(s); in.close(); } catch (IOException e) { throw new RuntimeException("管道读取失败"); } // 这种方法虽然OK,但是不适合代码原理展示 // PrintStream ps = new PrintStream(System.out); // int line = 0; // try // { //0-255的ASKII值 // while((line = in.read()) != -1) // { // // ps.println((char)line); // } // in.close(); // ps.close(); // } // catch (IOException e) // { // throw new RuntimeException("管道读取流失败"); // } } } class Write implements Runnable { private PipedOutputStream out; Write(PipedOutputStream out) { this.out = out; } public void run() { try { System.out.println("开始写入数据,等待6秒"); Thread.sleep(6000); out.write("da wang jiao wo lai xun shang".getBytes()); out.close(); } catch (Exception e) { throw new RuntimeException("管道输出流失败"); } } }
三十九.IO流操作基本数据类型的流对象DataStream
重点在于:可以用于操作基本数据类型的数据的流对象,把基本数据和流结合起来!!!!import java.io.*; class IoTextDemo { public static void main(String[] args)throws IOException { //writeData(); readData(); } public static void writeData()throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:\\hebing\\data.txt")); dos.writeInt(234); dos.writeBoolean(true); dos.writeDouble(9887.543); dos.close(); } public static void readData()throws IOException { //必须按照写的顺序读 DataInputStream dis = new DataInputStream(new FileInputStream("E:\\hebing\\data.txt")); int num = dis.readInt(); boolean b =dis.readBoolean(); double d = dis.readDouble(); System.out.println("num="+num); System.out.println("b="+b); System.out.println("d="+d); dis.close(); } //以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流。 public static void writeUTFDemo()throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:\\hebing\\data.txt")); dos.writeUTF("你好");//用什么编码写就必须要用什么编码读 dos.close(); } public static void readUTFDemo()throws IOException { DataInputStream dis = new DataInputStream(new FileInputStream("E:\\hebing\\data.txt")); String s = dis.readUTF(); System.out.println(s); dis.close(); } }
四十.用于操作字节数组的流对象
ByteArrayInputStream:在构造的时候,需要接受数据源,而且数据源是一个字节数组。ByteArrayOutputStream :在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数据,这就是数据的目的地(这就是他的重点)。
下面这几个原理都是一样的
*************************************************
操作字节数组
ByteArrayInputStream与ByteArrayOutputStream
操作字符数据
CharArrayReader与CharArrayWrite
操作字符串
StringReader与StringWriter
**************************************************
因为这两个流对象都操作的数组,并没有使用系统资源(底层资源)
所以,不用进行close关闭。而且关不关闭,这个流对象都能继续使用
[b]1.源设备,[/b]
键盘 System.in , 硬盘 FileStream , 内存ArrayStream !!!!!!!!!!
[b]2.目的设备:[/b]
控制台 System.out 硬盘FileStream, 内存ArrayStream. !!!!!!!!!!
这里的源和目的都是内存
用流的读写思想来操作数据
import java.io.*; class IoTextDemo { public static void main (String[] args) { //数据源 ByteArrayInputStream bis = new ByteArrayInputSream(“ABCDEFG”.getBytes());//都在内存中 //数据目的 ByteArrayOutputStream bos = new ByteArrayOutputStream();//都在内存中//不用写目的,因为目的被封装在内部,可变的字符数组 int by = 0; while((by = bis.read()) != -1) { bos.write(by); } System.out.println(bos.size()); //7 System.out.println(bos.toString()); //ABCDEFG } }
四十一.IO流转换流的字符编码
字符编码字符流的出现是为了方便操作字符
更重要的是加入了编码转换
原理:!!!!!!
通过子类转换流来完成
InputStreamReader
OutputStreamWriter
在两个对象进行构造的时候加入字符集(也就是编码表)
常见的编码表
ASCII:美国标准信息交换码
用一个字节的7位可以表示
ISO8859-1:拉丁码表。欧洲码表
用一个字节的8位表示(比如打头为1,怎么写都跟前面的都不一样)
GBK2312:中国的中文编码表。(两个字节高位都是1,兼容ASCII码)
GBK:中国的中文编码表升级,融合了更多的中文文字符号
Unicode:国际标准码,融合了多种文字
所有文字都用两个字节来表示,java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符
import java.io.*; class IoTextDemo { public static void main(String[] args) throw IOException { readText(); } } public static void readText() throws IOException { InputStreamReader isr = InputStreamReader(new FileInputStream(“gbk.txt”),”GBK”); char[] buf = new char[10]; int len = isr.read(buf); String str = new String (buf, 0, len); System.out.printlb(str); isr.close(); } public static void writeText() throws IOException { OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“utf.txt”),”UTF-8”); osw,write(“你好”); osw.close(); }
四十二.编码解码
编码:字符串变成字节数组解码:字节数组变成字符串
String -- >byte[] ;str.getBytes(charsetName);
byte -- > String: new String(byte[],charsetName);
import java.util.*; class EncideDemo { public static void main(String[] args) throws Exception { String s = “你好”; byte[] b1 = s.getBytes(“utf-8”); //编码 System.out.println(Arrays.toString(b1)); //打印出他的字节 String s1 = new String(b1 , “UTF-8”); System.out.println(“s1=”+s1); //解码 } //解码错了,在编回去,就OK了 public static void method_1() { String s = "你好"; byte[] b1 = s.getBytes("GBK"); System.out.println(Arrays.toString(b1)); //打印出按照GBK编码的每个字节 String s1 = new String (b1,"iso8859-1"); System.out.println("s1="+s1);//打印解码出的字符 byte[] b2 = s1.getBytes("iso8859-1"); System.out.println(Arrays.toString(b2)); //按照iso8859编码出的每个字节 String s2 = new String(b2,"gbk"); System.out.println("s2= "+s2); } !!!!! //解码错了,在编回去,不行了 //往回编的时候编错了,因为GBK,UTF-8都识别中文,服务器用的是IOS8859 //GBK用两个字节编码中文,UTF-8用三个,这是根本原因,用三个的原因,是因为识别到了使用三个字节的格式 //UTF编码原理 //utf编码是不定长编码,每一个字符的长度从1-6个字 //节不等。另外,utf编码自带简单的校验功能。一般来讲,英文字母都是用一个字节表示,而汉字使用三个字节 public static void method_2() { String s = "你好"; byte[] b1 = s.getBytes("GBK"); System.out.println(Arrays.toString(b1)); //打印出按照GBK编码的每个字节 String s1 = new String (b1,"UTF-8"); System.out.println("s1="+s1);//打印解码出的字符 byte[] b2 = s1.getBytes("UTF-8"); System.out.println(Arrays.toString(b2)); //按照iso8859编码出的每个字节 String s2 = new String(b2,"gbk"); System.out.println("s2= "+s2); } }
四十三.联通问题
UTF-8是读取三个字节成一个中文,怎么判断取一个字节,还是去两个字节,还是三个字节
联通这两个字的编码正好符合UTF-8取两个字节的规则,所以乱码,他是三个字节做一个中文
开头 0 读一个字节
字节 1 0
位 6-0
开头110
第二字节10 读两个字节
字节 1 1
1 0 位 10-6
字节 2 1
0 位 5-0
第三个字节
字节 1 1
1 1 0位 15-12
字节 2 1
0 位 11-6
字节 3 1
0 位 5-0
class EncodeDemo2 { public static void main(String[] args)throws Exception { String s = "联通"; byte[] by = s.getBytes("gbk"); for(byte b:by) { System.out.println(Integer.toBinaryString(b&255))//打印成二进制//取最后八位 } } }
四十四.练习
需求:有五个学生,每个学生有三门课的成绩
从键盘输入以上数据(包括姓名,三门课成绩),
输入的格式:如:zhangsan , 30 , 40 ,60计算出总成绩,
并把学生的信息和计算出的总分数高低顺序存档在磁盘文件”stud.txt”中
1.描述学生对象
2.定义一个可操作学生对象的工具类。
思想:
1.通过获取键盘录入一行数据,并将该行中的信息取出封装成对象。
2.因为学生有很多,那么就需要存储,使用到集合,因为对学生的总分排序
所以可以使用TreeSet.
3.将集合的信息写入到一个文件中。
import java.io.*; import java.util.*; class IoTextDemo { public static void main(String[] args) throws IOException { TreeSet<Student> stus = StudentInfoTool.getStudents();//默认顺序从小到大,现在从大到小 StudentInfoTool.writeToFile(stus); } } class StudentInfoTool { public static TreeSet<Student> getStudents()throws IOException { BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); TreeSet<Student> ts = new TreeSet<Student>(); String line = null; while((line = bufr.readLine()) != null) { if("over".equals(line)) { break; } //把输入的字符按逗号区分开 String[] info = line.split(","); //自己写的时候就卡在这个地方(怎么把输入的数据添加到集合中) //parseInt(String s)将字符串参数作为有符号的十进制数进行解析 Student stu = new Student(info[0],Integer.parseInt(info[1]),Integer.parseInt(info[2]),Integer.parseInt(info[3])); ts.add(stu); } bufr.close(); return ts; } public static void writeToFile(TreeSet<Student> ts1) throws IOException { BufferedWriter bufw = new BufferedWriter(new FileWriter("E:\\hebing\\Stu_info.txt") ); for(Student s:ts1) { bufw.write(s.toString()+'\t'); bufw.write(s.getSum()+""); bufw.newLine(); bufw.flush(); } bufw.close(); } } //因为要排序,所以选择TreeSet,这里就用排序两种方法之一实现Comparable class Student implements Comparable<Student> { private String name; private int cn; private int en; private int math; private int sum; Student(String name , int cn , int en , int math) { this.name = name; this.cn = cn; this.en = en; this.math = math; this.sum = cn+en+math; } public String getName() { return name; } public int getSum() { return sum; } public int hashCode() { return name.hashCode()+sum*2; } public boolean equals(Student obj) { return (this.name.equals(obj.name))&&(this.sum == obj.sum); } //继承comparable需要复写compareTo这个方法 public int compareTo(Student s) { //这个地方写错了!!!!! int num = new Integer(this.sum).compareTo(new Integer(s.sum)); if(num == 0) { return this.name.compareTo(s.name); } return num; } public String toString() { //等会把数据按照这样的格式写入文件中 return name+","+en+","+cn+","+math+","+sum; } }
相关文章推荐
- 黑马程序员_Java基础_IO流(四)_21
- Java基础-20总结,递归,IO流
- Java基础(19,20(1))IO流
- Java基础知识强化之IO流笔记21:FileInputStream读取数据
- Java基础知识_毕向东_Java基础视频教程笔记(19-21 IO流)
- Java基础21--IO流--装饰设计模式--缓冲流
- Java基础-21总结字符流,IO流编码问题,实用案例
- Java基础-20总结,递归,IO流
- Java基础20--IO流
- Java基础-21总结字符流,IO流编码问题,实用案例必做一遍
- Java基础知识强化之IO流笔记20:FileOutputStream写出数据实现换行和追加写入
- 黑马程序员_Java基础_IO流(三)_20
- Java基础知识_毕向东_Java基础视频教程笔记(19-21 IO流)
- 黑马程序员_java基础视频第18天_与系统交互的类及IO流
- Java基础21天--03--IO流
- Java基础20天--05--IO流
- Java基础21-反射
- 黑马程序员_毕向东_Java基础视频教程第十八天-IO流---学习笔记
- Java基础21天--04--IO流
- Java基础19天--05--IO流