7、map集合和IO流


Map:一次添加一对元素。Collection 一次添加一个元素。
Map也称为双列集合,Collection集合称为单列集合。
其实map集合中存储的就是键值对。 map集合中必须保证键的唯一性。 

常用方法:
1,添加。
value put(key,value):返回前一个和key关联的值,如果没有返回null.

2,删除。
void  clear():清空map集合。
value remove(key):根据指定的key翻出这个键值对。 

3,判断。
boolean containsKey(key):
boolean containsValue(value):
boolean isEmpty();

4,获取。 
value get(key):通过键获取值,如果没有该键返回null。
当然可以通过返回null,来判断是否包含指定键。 
int size(): 获取键值对的个数。 

Map常用的子类:
|--Hashtable :内部结构是哈希表,是同步的。不允许null作为键,null作为值。
|--Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
|--HashMap : 内部结构是哈希表,不是同步的。允许null作为键,null作为值。
|--TreeMap : 内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。 

练习:

<span style="font-size:14px;">package 面试题;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

//练习:
/*“adjankjdaopkdldmd”获取该字符串中字母出现的次数*/
public class MapText {

	public static void main(String[] args) {
		
		String str = "adjankjdaopkdldmd";
		String s = show(str);
		System.out.print(s);
	}

	public static String show(String str) {
		
		//将字符串变成字符数组
		char[] c = str.toCharArray();
		
		//定义map集合
		Map<Character, Integer > me = new TreeMap<Character,Integer >();
		
		for(int i = 0; i < c.length; i ++ ){
			int count = 0;
			Integer value = me.get(c[i]);
			if(value != null)
				count = value;
			count ++;
			me.put(c[i], count);
		}
		
		return myToString(me);
	}

	private static String myToString(Map<Character, Integer> me) {
		// TODO 自动生成的方法存根
		StringBuilder sb = new StringBuilder();
		Iterator<Character> i = me.keySet().iterator();
		while(i.hasNext()){
			
			Character key = i.next();
			Integer value = me.get(key);
			
			sb.append(key + "("+value+")");
		}
			
		return sb.toString();
	}

}
</span>
运行结果

<span style="font-size:14px;">a(3)d(5)j(2)k(2)l(1)m(1)n(1)o(1)p(1)</span>

foreach语句:
格式:
for(类型  变量   :Collection集合|数组)
 {
 
}

传统for和高级for的区别?
传统for可以完成对语句执行很多次,因为可以定义控制循环的增量和条件。

高级for是一种简化形式。
 它必须有被遍历的目标。该目标要是数组,要么是Collection单列集合。

对数数组的遍历如果仅仅是获取数组中的元素,可以使用高级for。如果要对数组的角标进行操作建议使用传统for。 

IO流

输入流和输出流相对于内存设备而言.
将外设中的数据读取到内存中:输入
将内存的数写入到外设中:输出。

字符流的由来:
其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表。获取对应的文字。
在对这个文字进行操作。简单说:字节流+编码表 

字节流的两个顶层父类:
1,InputStream  2,OutputStream.

字符流的两个顶层父类:
1,Reader 2,Writer

这些体系的子类都以父类名作为后缀。 而且子类名的前缀就是该对象的功能。


装饰设计模式:对一组对象的功能进行增强时,就可以使用该模式进行问题的解决。

装饰比继承更灵活。装饰类和被装饰类都必须所属同一个接口或者父类。


为了方便字符和字节之间的转换操作,IO流中有两个转换流:

InputStreamReader 字节流通向字符流的桥梁

OutputStreamWriter 字符流通向字节流的桥梁


为了提高字符的读写效率,IO流中有两个对象BufferedReader和BufferedWriter字符缓冲流。

BufferedReader和BufferedWriter演示。

<span style="font-size:14px;">package iodemo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
 * 需求:在控制台打印数据,转换成大写输出,“over”结束。
 * @author Administrator
 *
 */

public class BufferedReaderBufferedWriterDemo {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		
		show();
	}
	
	public static void show() throws IOException
	{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		String s;
		while((s = br.readLine())!=null)
		{
			if(s.equals("over"))
				break;
			bw.write(s.toUpperCase());
			bw.newLine();
			bw.flush();
		}
	}
}</span>

IO流的操作规律总结:

1,明确体系:

数据源:InputStream ,Reader

数据汇:OutputStream,Writer


2,明确数据:因为数据分两种:字节,字符。

数据源:是否是纯文本数据呢?是:Reader 否:InputStream

数据汇:是:Writer 否:OutputStream

到这里就可以明确具体要使用哪一个体系了。剩下的就是要明确使用这个体系中的哪个对象。

 

3,明确设备:

数据源:键盘:System.in硬盘:File内存:数组。网络:socket  socket.getInputStream();

 数据汇:控制台:System.out硬盘:File内存:数组网络:socket socket.getOutputStream();

 

4,明确额外功能:

1,需要转换?是,使用转换流。InputStreamReader OutputStreamWriter

2,需要高效?是,使用缓冲区。Buffered

3,需要其他?


1,复制一个文本文件。

1,明确体系:

源:InputStream ,Reader

目的:OutputStream ,Writer

2,明确数据:

源:是纯文本吗?是 Reader

目的;是纯文本吗?是 Writer

3,明确设备:

源:硬盘上的一个文件。  FileReader

目的:硬盘上的一个文件。FileWriter


FileReader fr = new FileReader("a.txt"); FileWriterfw= new FileWriter("b.txt");

4,需要额外功能吗?

需要,高效,使用buffer

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));


2,读取键盘录入,将数据存储到一个文件中。

1,明确体系:

源:InputStream ,Reader

目的:OutputStream ,Writer

2,明确数据:

源:是纯文本吗?是 Reader

目的;是纯文本吗?是 Writer 3,明确设备:

源:键盘,System.in 目的:硬盘,FileWriter

InputStream in = System.in;

FileWriter fw = new FileWriter("a.txt");

4,需要额外功能吗?

需要,因为源明确的体系时Reader。可是源的设备是System.in。 所以为了方便于操作文本数据,将源转成字符流。需要转换流。

InputStreamReader

InputStreamReader isr = new InputStreamReader(System.in);

FileWriter fw  = new FileWriter("a.txt");

需要高效不?需要。Buffer

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); 

BufferedWriter bufw = new BufferedWriter(new FileWriter("a.txt"));


3,读取一个文本文件,将数据展现在控制台上。

1,明确体系:

源:InputStream ,Reader

目的:OutputStream ,Writer

2,明确数据:

源:是纯文本吗?是 Reader

目的;是纯文本吗?是 Writer

3,明确设备:

源:硬盘文件,FileReader。

目的:控制台:System.out。

FileReader fr = new FileReader("a.txt"); OutputStream out = System.out;

4,需要额外功能?

因为源是文本数据,确定是Writer体系。所以为了方便操作字符数据,

需要使用字符流,但是目的又是一个字节输出流。

需要一个转换流,OutputStreamWriter 

FileReader fr = new FileReader("a.txt");

OutputStreamWriter osw = new OutputStreamWriter(System.out);

需要高效吗?需要。

BufferedReader bufr = new BufferedReader(new FileReader("a.txt")); 

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));


4,读取键盘录入,将数据展现在控制台上。

1,明确体系:

源:InputStream ,Reader

目的:OutputStream ,Writer

2,明确数据:

源:是纯文本吗?是 Reader

目的;是纯文本吗?是 Writer 3,明确设备:

源:键盘:System.in 目的:控制台:System.out

InputStream in = System.in; OutputStream out = System.out;

4,需要额外功能吗?

因为处理的数据是文本数据,同时确定是字符流体系。

为方便操作字符数据的可以将源和目的都转成字符流。使用转换流。 为了提高效率,使用Buffer

BufferedReader bufr  =new BufferedReader(newInputStreamReader(Systme.in));

BufferedWriter bufw  =  new BufferedWriter(new OutputStreamWriter(System.out));


5,读取一个文本文件,将文件按照指定的编码表UTF-8进行存储,保存到另一个文件中。

1,明确体系:

源:InputStream ,Reader

目的:OutputStream ,Writer

2,明确数据:

源:是纯文本吗?是 Reader

目的;是纯文本吗?是 Writer

3,明确设备:

源:硬盘:FileReader.

目的:硬盘:FileWriter

FileReader fr = new FileReader("a.txt"); FileWriter fw =new FileWriter("b.txt");

4,额外功能:

注意:目的中虽然是一个文件,但是需要指定编码表。

而直接操作文本文件的FileWriter本身内置的是本地默认码表。无法明确具体指定码表。

这时就需要转换功能。OutputStreamWriter,而这个转换流需要接受一个字节输出流,而且对应的目的是一个文件。这时就使用字节输出流中的操作文件的流对象。FileOutputStream.

FileReader fr = new FileReader("a.txt"); 

OutputStreamWriter osw = new OutputStreamWriter(newFileOutputStream("b.txt"),"UTF-8");

需要高效吗?

BufferedReader bufr = new BufferedReader(new FileReader("a.txt")); 

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt"),"UTF-8"));


目前为止,10个流对象重点掌握。 

字符流:

FileReader FileWriter

BufferedReader BufferedWriter

InputStreamReader OutputStreamWrier

字节流:

FileInputStream FileOutputStream

BufferedInputStreamBufferedOutputStream


File类:

用于将文件和文件夹封装成对象。

1,创建。

boolean createNewFile();如果该文件不存在,会创建,如果已存在,则不创建。不会像输出流一样会覆盖。

boolean mkdir(); boolean mkdirs();创建文件和创建多重文件夹

2,删除。

boolean delete();void deleteOnExit();

3,获取:

String getAbsolutePath();String getPath();

String getParent();

String getName();longlength();

long lastModified();

4,判断:

boolean exists();boolean isFile(); boolean isDirectory();


IO中的其他功能流对象:


1,打印流:

PrintStream:字节打印流。

特点:

1,构造函数接收File对象,字符串路径,字节输出流。意味着打印目的可以有很多。

2,该对象具备特有的方法 打印方法 print println,可以打印任何类型的数据。

3,特有的print方法可以保持任意类型数据表现形式的原样性,将数据输出到目的地。

对于OutputStream父类中的write,是将数据的最低字节写出去。


PrintWriter:字符打印流。 特点:

1,当操作的数据是字符时,可以选择PrintWriter,比PrintStream要方便。

2,它的构造函数可以接收 File对象,字符串路径,字节输出流,字符输出流。

3,构造函数中,如果参数是输出流,那么可以通过指定另一个参数true完成自动刷新,该true对

println方法有效。

 

什么时候用?当需要保证数据表现的原样性时,就可以使用打印流的打印方法来完成,这样更为方便。保证原样性的原理:其实就是将数据变成字符串,在进行写入操作。


SequenceInputStream:

特点: 

1,将多个字节读取流和并成一个读取流,将多个源合并成一个源,操作起来方便。

2,需要的枚举接口可以通过Collections.enumeration(collection);


ObjectInputStream 和 ObjectOutputStream

对象的序列化和反序列化。

 writeObject  readObject

Serializable标记接口

 关键字:transient:非静态数据不想使用序列化,可使用该关键字。


RandomAccessFile:

特点:

1,即可读取,又可以写入。

2,内部维护了一个大型的byte数组,通过对数组的操作完成读取和写入。

3,通过getFilePointer方法获取指针的位置,还可以通过seek方法设置指针的位置。

4,该对象的内容应该封装了字节输入流和字节输出流。

5,该对象只能操作文件。

 

通过seek方法操作指针,可以从这个数组中的任意位置上进行读和写 可以完成对数据的修改。

但是要注意:数据必须有规律。

 

管道流:需要和多线程技术相结合的流对象。PipedOutputStreamPipedInputStream

用操作基本数据类型值的对象: DataInputStreamDataOutputStream

设备是内存的流对象。

ByteArrayInputStream ByteArrayOutputStream CharArrayReader   CharArrayWriter


IO流体系:

字符流:

Reader

|--BufferedReader:

|--LineNumberReader

|--CharArrayReader

|--StringReader

|--InputStreamReaer

|--FileReade


Writer

|--BufferedWriter

|--CharArrayWriter

|--StringWriter

|--OutputStreamWriter

|--FileWriter

|--PrintWriter


字节流:

InputStream

|--FileInputStream:

|--FilterInputStream

|--BufferedInputStream

|--DataInputStream

|--ByteArrayInputStream

|--ObjectInputStream

|--SequenceInputStream

|--PipedInputStream


OutputStream

|--FileOutputStream

|--FilterOutputStream

|--BufferedOutputStream

|--DataOutputStream

|--ByteArrayOutputStream

|--ObjectOutputStream

|--PipedOutputStream

|--PrintStream


练习复制文件:

package iodemo;
/**
 *演示复制文件
 */
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyMusic {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub

		copy3();
	}

	private static void copy1() throws IOException {
		// TODO Auto-generated method stub
		FileInputStream fi = new FileInputStream("c:\\陶喆 - 寂寞的季节.ape");
		FileOutputStream fo = new FileOutputStream("d:\\陶喆 - 寂寞的季节.ape");
		
		byte[] buf = new byte[10240];
		int len = 0;
		while((len = fi.read(buf))!=-1){
			fo.write(buf, 0, len);
		}
		fi.close();
		fo.close();
	}
	private static void copy2() throws IOException {
		// TODO Auto-generated method stub
		FileInputStream fi = new FileInputStream("c:\\陶喆 - 寂寞的季节.ape");
		BufferedInputStream bi =new BufferedInputStream(fi);
		FileOutputStream fo = new FileOutputStream("d:\\陶喆 - 寂寞的季节.ape");
		BufferedOutputStream bo =new BufferedOutputStream(fo);
		
		int len = 0;
		while((len = bi.read())!=-1){
			bo.write(len);
		}
		bi.close();
		bo.close();
	}
	private static void copy3() throws IOException {
		// TODO Auto-generated method stub
		FileInputStream fi = new FileInputStream("c:\\陶喆 - 寂寞的季节.ape");
		FileOutputStream fo = new FileOutputStream("d:\\陶喆 - 寂寞的季节.ape");
		
		byte[] buf = new byte[fi.available()];
		fi.read(buf);
		fo.write(buf);
		
		fi.close();
		fo.close();
	}

	
}
练习:深度遍历
package iodemo;

import java.io.File;

/**
 * 深度遍历
 * 需求:对指定的目录进行所有内容列出(包含子目录内容)
 * @author mc
 *
 */
public class Text2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		File files = new File("d:\\java") ;
		listAll(files,0);
	}

	public static void listAll(File files, int level) {
		// TODO Auto-generated method stub
		level ++;
		System.out.println(getSpace(level)+"文件夹:"+files.getAbsolutePath());
		File[] f = files.listFiles();
		for(int x = 0; x < f.length; x ++)
		{
			if(f[x].isDirectory())
				listAll(f[x],level);
			else
				System.out.println(getSpace(level)+"文件"+f[x].getAbsolutePath());
		}
	}

	private static String getSpace(int level) {
		// TODO Auto-generated method stub
		StringBuilder sb = new StringBuilder();
		for(int i = 0;i < level; i ++)
			sb.append("--");
		return sb.toString();
	}

}

练习:使用次数
package iodemo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

/**
 * 需求:定义一个功能,记录一个程序的使用次数,如果超过五次,则给出使用次数已到请注册,并不再运行应用程序
 * 
 * 思路:
 * 1、记录数据用到计数器,定义一个计数器,每用一次,计数器加一
 * 2、计数器要持久保存,当内存结束时,使用次数仍然记录在硬盘中。
 * 3、记录次数要声明,方便阅读,就用到了map集合,又要操作硬盘数据,用到IO流
 * 		map + IO = properties
 * @author mc
 *
 */

public class Text3 {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		show();
	}

	public static void show() throws IOException {
		// TODO Auto-generated method stub
		
		//创建配置文件,并封装成对象
		File conFile = new File("count.properties");
		
		//判断文件是否存在
		if(!conFile.exists())
			conFile.createNewFile();
		
		//创建输入流读取配置文件
		FileInputStream is = new FileInputStream(conFile);
		
		//创建集合properties,记录使用次数
		Properties pp = new Properties();
		pp.load(is);
		String value = pp.getProperty("time");
		
		//定义计数器
		int count = 0;
		if(value!=null){
			 count = Integer.parseInt(value);
			 if(count > 5)
				 throw new Error("使用次数已达上线,请注册后再使用");
		}
		count ++;
		
		//将键值添加到集合中去
		pp.setProperty("time", count+"");
		
		//将集合内容传到配置文件中
		FileOutputStream fos = new FileOutputStream(conFile);
		pp.store(fos, "properties");
		
		is.close();
		fos.close();
	}

}

练习:创建文件切割器

package 复习;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;

/**
 * 创建一个文件切割器;
 * @author Administrator
 *
 */
public class SplitFileDemo {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		
		File file = new File("D:\\陶喆 - 寂寞的季节.ape");
		File dir = new File("G:\\陶喆 - 寂寞的季节");
		if(!dir.exists())
			dir.mkdirs();
		splitFile(file, dir  );
		File f1 = new File("G:\\");
		File d1 = new File("G:\\陶喆 - 寂寞的季节");
		mergeFile(f1,d1);
	}

	public static void splitFile(File file, File dir) throws IOException {
		// TODO Auto-generated method stub
		
		//输入流读取源文件
		FileInputStream fis = new FileInputStream(file);
		byte[] buf = new byte[1024*1024*5];
		int len = 0;
		int count = 1;
		

		//创建输出流,获取数据
		FileOutputStream fos = null;
		while((len = fis.read(buf)) != -1){
			
			fos = new FileOutputStream(new File(dir,(count++) + ".part"));
			fos.write(buf, 0, len);
			fos.close();
		}
		
		//创建配置文件,用于合并时使用
		Properties prop = new Properties();
		prop.setProperty("filecount", count+"");
		prop.setProperty("filename", file.getName());
		
		fos = new FileOutputStream(new File(dir,count + ".properties"));
		
		//将Properties中的信息持久性的储存到文件中
		prop.store(fos, "split file info");

		fis.close();
		fos.close();
		
	}

	public static void mergeFile(File file, File dir) throws IOException{
		
		//读取配置文件,获取信息
		File[] files = dir.listFiles(new Suffix(".properties"));
		if(files.length!=1)
			throw new RuntimeException("配置文件不存在或不唯一");
		Properties prop = new Properties();
		FileInputStream os = new FileInputStream(files[0]);
		
		//加载,读取配置文件内容
		prop.load(os);
		String name = prop.getProperty("filename") ;
		int count =Integer.parseInt( prop.getProperty("filecount")) ;
		
		//定义集合,储存文件碎片
		ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
		for(int i = 1; i < count; i ++){
			al.add(new FileInputStream(new File(dir,i + ".part")));
		}
		
		//利用工具类方法,将集合变成枚举
		Enumeration<FileInputStream> en = Collections.enumeration(al);
		//创建序列流,将含文件碎片的枚举,变成流对象
		SequenceInputStream sis = new SequenceInputStream(en);
		
		//创建输出流,碎片合成文件
		FileOutputStream fos = new FileOutputStream(new File(file,name));
		byte[] buf = new byte[1024*1024*2];
		int len = 0;
		while((len = sis.read(buf))!=-1)
		{
			fos.write(buf, 0, len);
		}
		
		sis.close();
		fos.close();
	}
}

练习:按字节截取字符串
package 复习;

import java.io.IOException;

/**
 * 需求:切割字符串“aa黑马程序员”,如果字符是半个就舍弃
 * @author Administrator
 *
 */
public class CutString {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		String str = "aa黑马程序员";
		
		for(int len = 1; len <= str.getBytes("gbk").length;len ++)
		{
			System.out.println(cutString(str, len));
	
		}
	}
	public static String cutString(String str, int len) throws IOException {
		// TODO Auto-generated method stub
		byte[] buf = str.getBytes("gbk");
		int count = 0;
		
		for(int x = len -1; x >= 0; x --)
		{
			if(buf[x]<0)
				count ++;
			else
				break;
		}
		if(count%2==0)
			return new String(buf,0,len,"gbk");
		else
			return new String(buf,0,len-1,"gbk");
	}

}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值