Java=字节流,字符流,Properties

1.字符流
2.IO流异常处理
3.Properties属性集
4.ResourceBundle工具类(专门用于属性集保存之后的文件)

一,字符流

首先字节流也是可以读取文本文件的!!!但是可能会出现一种状况,读取中文时只读取其中一般,因为中文不只由一个字节组成.
为了解决这个问题,引入了字符流,以字符作为单位来操作!!

字符输入流:

顶层父类:Reader 抽象类

顶层父类: Reader(抽象类)
    
共性方法:
	public void close(); 释放资源
        
    public int read(); 一次读一个字符  
    public int read(char[] chs); 一次读取一个字符数组,返回值表示实际读取的字符个数   

FileReader类

文件的字符输入流(从文件中读取字符数据)

构造方法
public FileReader(String path);
public FileReader(File file);

public class TestFileReader01 {
    public static void main(String[] args) throws Exception {
        //1.创建一个FileReader对象
        FileReader fr = new FileReader("1.txt");
//        FileReader fr = new FileReader(new File("1.txt"));
        /**
         * 以上构造干了三件事!!
         * a.创建对象fr
         * b.判断文件是否存在
         *      如果存在,不清空!!!
         *      如果不存在,报错!
         * c.绑定fr和1.txt文件
         */
    }
}

读取一个字符

.读取一个字符
public class TestFileReader02 {
    public static void main(String[] args) throws Exception {
        //1.创建一个FileReader对象
        FileReader fr = new FileReader("1.txt");

        //2.一次读一个字符
        //int ch = fr.read();
        //System.out.println((char) ch);
        //===========一次读取一个字符的标准循环代码===========
        int ch = 0; //用来保存读取到的字符
        /**
         * (ch = fr.read()) != -1
         * 以上代码干了三件事!!
         * a.读取 fr.read();
         * b.赋值 ch = 读到的字符
         * c.判断 ch != -1
         */
        while ((ch = fr.read()) != -1) {
            System.out.println((char) ch);
        }
        //3.释放资源
        fr.close();
    }
}

读取一个字符数组

public class TestFileReader03 {
    public static void main(String[] args) throws Exception {
        //1.创建一个FileReader对象
        FileReader fr = new FileReader("1.txt");
        //2.一次读一个字符数组
        //char[] chs = new char[4];
        //int len = fr.read(chs);
        //System.out.println("实际读取到"+len+"个字符");
        //System.out.println(new String(chs,0,len));
        char[] chs = new char[4]; //保存字符数据的数组
        int len = 0;//保存实际读取的个数
        /**
         * (len = fr.read(chs)) != -1
         * 以上代码也是干了三件事!!!
         * a.读取 fr.read(chs);
         * b.赋值 len = 实际读取的个数
         * c.判断 len != -1
         */
        while ((len = fr.read(chs)) != -1) {
            System.out.println(new String(chs,0,len));
        }     
        //3.释放资源
        fr.close();
    }
}

字符输出流

顶层父类:Writer(抽象类)

顶层父类:Writer(抽象类)
    
共性方法:
	public void close();//释放资源
	public void flush();//对于字符流来说有用!!

	public void write(int ch); //写一个字符

	public void write(char[] chs); //写一个字符数组
	public void write(char[] chs,int startIndex,int len); //写一个字符数组的一部分

	public void write(String str);// 直接写一个字符串
	public void write(String str,int startIndex,int len);// 直接写一个字符串的一部分

.FileWriter类

文件的字符输出流(向文件中写字符数据)

构造方法
public FileWriter(String path);
public FileWriter(File file);

public class TestFileWriter01 {
    public static void main(String[] args) throws IOException {
        //1.创建一个FileWriter对象
        FileWriter fw = new FileWriter("2.txt");
//        FileWriter fw = new FileWriter(new File("2.txt"));
        /**
         * 以上构造干了三件事
         * a.创建对象fw
         * b.判断文件是否存在
         *      如果存在,清空文件内容
         *      如果不存在,会创建文件
         * c.绑定fw和2.txt
         */
    }
}

写出字符数据的三种方法

public void write(int ch); //写一个字符

public void write(char[] chs); //写一个字符数组
public void write(char[] chs,int startIndex,int len); //写一个字符数组的一部分

public void write(String str);// 直接写一个字符串
public void write(String str,int startIndex,int len);// 直接写一个字符串的一部分

public class TestFileWriter02 {
    public static void main(String[] args) throws IOException {
        //1.创建一个FileWriter对象
        FileWriter fw = new FileWriter("2.txt");
        //2.写数据
        //a.写一个字符
        fw.write('a');
        fw.write('中');
        //b.写一个字符数组
        char[] chs = {'中','国','j','a','v','a','!'};
        fw.write(chs);
        //c.写一个字符数组的一部分
        fw.write(chs,3,2);
        //d.直接写一个字符串
        fw.write("中国万岁我爱你Java,你爱我吗?");
        //e.直接写一个字符串的一部分
        fw.write("中国万岁我爱你Java,你爱我吗?",0,4);
        //3.释放资源
        fw.close();
    }
}

关闭和刷新的区别

flush(); 只会刷新缓冲区,不关闭流,流可以继续使用
close(); 不仅会刷新缓冲区,还会关闭流,流不能继续使用  
    
public class TestFileWriter03 {
    public static void main(String[] args) throws IOException {
        //1.创建一个FileWriter对象
        FileWriter fw = new FileWriter("3.txt");
        //2.写数据
        fw.write("php");
        //3.刷新缓冲
        fw.flush();
        //再次写数据,OK的
        fw.write("python");
        fw.flush();
        //4.释放资源
        fw.close();
        //再次写数据,报错,流已经关闭
        fw.write("python");
        fw.flush();
    }
}    

.续写和换行

如何续写: 只要使用下面这个两个构造即可
	public FileWriter(String path,boolean append);//append表示是否需要续写
	public FileWriter(File file,boolean append);//append表示是否需要续写

public class TestFileWriter04 {
    public static void main(String[] args) throws IOException {
        //1.创建一个FileWriter对象,保证续写
        FileWriter fw = new FileWriter("3.txt", true);
        //2.续写
        fw.write("python");
        //3.释放资源
        fw.close();
    }
}
如何换行: 很简单!!! 向文件中写一个换行符即可
    windows: \r\n(windows系统必须使用\r\n)
    Linux:  \n
    MacOS: \r (MacOSX以及以后的系统,也是\n)
 
public class TestFileWriter05 {
    public static void main(String[] args) throws IOException {
        //1.创建一个FileWriter对象
        FileWriter fw = new FileWriter("4.txt");
        //2.写数据
        for (int i = 0; i < 10; i++) {
            fw.write("c++\r\n");
//            fw.write("\r\n");
        }
        //3.释放资源
        fw.close();
    }
}        

二。IO流的异常处理

.JDK7之前的标准IO处理

//IO流异常的标准处理方式(JDK1.7以前)
public static void method01() {
    //1.创建FileReader
    FileReader fr = null;
    try {
        fr = new FileReader("1.txt");
        //2.读
        int ch = fr.read();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    } finally {
        //写释放资源的代码
        //3.释放资源
        try {
            if (fr != null) {
                fr.close();
            }
        } catch (IOException ie) {
            ie.printStackTrace();
        }
    }
}

.JDK7引入的IO处理

try-with-resource(和资源一起try)
格式:
	try(创建资源的代码;创建资源的代码;创建资源的代码){
        
    }catch(XxxException e){
        
    }

//IO流异常的标准处理方式(JDK1.7)
public static void method02() {
    try (FileReader fr = new FileReader("1.txt")) {
        int ch = fr.read();
        System.out.println((char) ch);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

三。Properties类

Properties类介绍

java.util.Properties 继承于 Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及
其对应值都是一个字符串。该类也被许多 Java 类使用,比如获取系统属性时, System.getProperties 方法就是
返回一个 Properties 对象
a.Properties就是一个双列集合(Properties extends HashTable extends Dictionary implments Map)
b.Properties的键和值已经确定为String了 
c.通过System类的静态方法.getProperties()可以获取系统先关的一些键值对
        public static void main(String[] args) {
                
        //        System.exit(0); //退出JVM
        //        long timeMillis = System.currentTimeMillis();//获取当前时间的毫秒值
                Properties ps = System.getProperties();//获取系统相关的一些键值对
                System.out.println(ps);// 
        }

构造方法

public Properties(); //创建一个空的Properties对象

public static void main(String[] args) {
    //1.创建一个空的Properties对象
    Properties ps = new Properties();
    System.out.println(ps);
}

基本保持数据的方法

Map接口中定义的方法:
	增:  put(键,值)
    删:  remove(键)
    改:  put(键,值)
    查:  get(键)
    遍历的两个方法:
	Set<键的类型> keys = map.keySet();
	Set<Map.Entry<K,V>> entrys = map.entrySet();

Properties也具有以上方法,但是我们一般使用其特有方法
    public Object setProperty(String key, String value);添加/修改键值对, 和put功能是一样的
    public String getProperty(String key); 以键找值,和get功能是一样
    public Set<String> stringPropertyNames();获取所有属性名的集合,和keySet功能是一样
    
public class PropertiesDemo02 {
    public static void main(String[] args) {
        //1.创建一个空的Properties对象
        Properties ps = new Properties();
        System.out.println(ps);
        //2.添加属性(键值对)
        ps.setProperty("xiaomi","688");
        ps.setProperty("huawei","888");
        ps.setProperty("vivo","222");
        System.out.println(ps);
        //3.修改
        ps.setProperty("vivo","333");
        System.out.println(ps);
        //4.获取
        System.out.println(ps.getProperty("huaei"));
        //5.获取所有的属性名(键!)
        Set<String> propertyNames = ps.stringPropertyNames();// 和 keySet
        System.out.println(propertyNames);
    }
}    

与流相关的方法

Properties有两个和流相关的方法,一个叫保存,一个加加载
    public void store(OutputStream out,String 说明内容); //保存Properties对象中的数据
	public void store(Writer write,String 说明内容);//保存Properties对象中的数据

	public void load(InputStream in);//把Properties文件内容加到当前对象
	public void load(Reader r);//把Properties文件内容加到当前对象

public class PropertiesDemo03 {
    public static void main(String[] args) throws Exception {
        //1.创建一个空的Properties对象
        Properties ps = new Properties();
        //2.添加
        ps.setProperty("username","root");
        ps.setProperty("password","1331");
        //3.保存,规范,文件名建议使用.properties作为后缀
        ps.store(new FileOutputStream("6.properties"),"this is a test file");
        //4.加载
        ps.load(new FileInputStream("6.properties"));
        System.out.println(ps);
    }
}
注意: 一般我们不会使用Properties文件来保存中文数据

四。ResourceBundle工具列

.ResourceBundle类的介绍

java.util.ResourceBundle 它是一个抽象类,我们可以使用它的子类 PropertyResourceBundle 来读取以 .properties
结尾的配置文件。

ResourceBundle实际上是一个抽象类,他的子类PropertyResourceBundle,可以读取以.properties为后缀的文件中的内容

.ResourceBundle类对象的创建

ResourceBundle类中提供了一个静态方法,用于获得它的子类对象(抽象类不能创建对象!)

使用指定的基本名称,默认语言环境和调用者的类加载器获取资源包。
public static ResourceBundle getBundle(String baseName); 用于绑定指定的.properties资源文件

注意:
	a.xxx.properties文件必须放在类的根路径下(src文件夹下)
    b.给定参数时,我们只需要给文件名的名字,不需要写文件的后缀  
public class ResourceBundleDemo {
    public static void main(String[] args) {
        //1.创建一个ResourceBundle实现类的对象
        ResourceBundle resourceBundle = ResourceBundle.getBundle("data");
        System.out.println(resourceBundle);
    }
}      

ResourceBundle读取配置文件操作

ResourceBundle类提供了一个getString(String key)方法用于读取配置文件中指定key的值

String getString(String key) 从此资源束或其父项之一获取给定密钥的字符串

public String getString(String key);

public class ResourceBundleDemo {
    public static void main(String[] args) {
        //1.创建一个ResourceBundle实现类的对象
        ResourceBundle resourceBundle = ResourceBundle.getBundle("data");
        System.out.println(resourceBundle);
        //2.根据键获取值
        String password = resourceBundle.getString("password");
        String username = resourceBundle.getString("username");
        //3.打印
        System.out.println(username);
        System.out.println(password);
    }
}

总结:

排序的工具类
    对数组进行排序: Arrays.sort(数组,new Comparator<数组的元素类型>(){});
    对List集合排序: Collections.sort(List集合,new Comparator<集合中元素类型>(){})
    对Set集合排序: 并不是所有的Set都能排序的,TreeSet才可以排序
    TreeSet怎么排序:   TreeSet set = new TreeSet(new 比较器对象())  
    写排序算法: 冒泡排序,选择排序,插入排序,希尔排序,快速排序,堆排序,归并排序... 

其他:

 请用户从控制台输入信息,程序将信息存储到文件Info.txt中。可以输入多条信息,每条信息存储一行。当用户输入:”886”时,程序结束。
public static void zy11() throws  Exception{
        File file = new File("Info.text");
        if (!file.exists()){
            file.createNewFile();
        }
        Scanner scn = new Scanner(System.in);
        FileWriter fw = new FileWriter(file);
        while (true){
            System.out.println("请选择:退出请按886, 添加学生按任意键");
            String flag = scn.nextLine();
            if (flag.equalsIgnoreCase("886")){
                fw.close();
                System.exit(0);
                break;
            }else{
                System.out.println("请输入学生信息:");
                System.out.println("学号:");
                String id = scn.nextLine();
                System.out.println("姓名:");
                String name = scn.nextLine();
                System.out.println("性别:");
                String sex = scn.nextLine();
                System.out.println("年龄:");
                String age = scn.nextLine();
                fw.write("id="+id+",name="+name+",sex="+sex+",age="+age);
                fw.write("\r\n");
            }
        }
    }
//有一个文本文件score.txt,只知道数据是键值对形式的,但不知道内容是什么。请写一个程序判断是否
//有"lisi"这样的键存在,如果有就改变其值为"120"

 public static void main(String[] args) throws Exception{
        Properties properties = new Properties();
        properties.load(new FileInputStream("score.txt"));
        FileOutputStream fileOutputStream = new FileOutputStream("score.txt");
        Set<String> strings = properties.stringPropertyNames();
        if (strings.contains("lisi")){
            System.out.println("存在lisi");
            properties.setProperty("lisi","100");
            properties.store(fileOutputStream,"--");
        }else {
            System.out.println("不存在lisi这个键");
        }

    }

面试题:

  1. 如何判断一个字符串中某个字符出现的次数?
  2. 如何反转一个字符串?

==String常用的方法有哪些?

  1. length
  2. equals
  3. trim
  4. substring
  5. concat
  6. indexOf
  7. lastIndexOf
  8. replace
  9. split
  10. toLowerCase
  11. toUpperCase
  12. valueOf()
  13. parseInt()
  14. contains()
  15. toCharArray()
  16. endsWith()
  17. startsWith()

关于问题1,如何判断一个字符串中某个字符串出现的次数呢?

。一般第一反应是 先把字符串转换为字符数组,然后使用foreach循环。在循环体内进行字符比对,如下:

public static void main(String[] args) {
    String str = "abcabc123abc";
    char searchChar = 'a';

    int count = 0;
    char[] charArray = str.toCharArray();
    for (char item : charArray) {
        if (item == searchChar) {
            count++;
        }
    }

    System.out.println("字符" + searchChar + "出现的次数为:" + count);
}

一般面试不会这么简单,增加了限制条件,

若不能使用循环,只使用String自己的方法,如何实现呢?

所以推荐使用replace()

public static void main(String[] args) {
    String str = "abcabc123abc";
    String searchChar = "a";
    int count = 0;

    int origialLength = str.length();
    str = str.replace(searchChar, "");
    int newLength = str.length();

    count = origialLength - newLength;

    System.out.println("字符" + searchChar + "出现的次数为:" + count);
}

2.如何反转一个字符串呢?

大部分人可能直接思路这样的

public static void main(String[] args) {
    String str = "abcabc123abc";

    StringBuilder stringBuilder = new StringBuilder(str);
    stringBuilder.reverse();

    String newStr = stringBuilder.toString();

    System.out.println("反转前:" + str);
    System.out.println("反转后:" + newStr);
}

但是面试官可能并不是他想要的而是:

可以利用数据结构中的栈,因为栈的特点是先入后出(这里可以提一下和队列的不同,队列的特点是先入先出),先把字符串中的每个字符按顺序入栈,再依次出栈,即可实现字符串的反转。

public static void main(String[] args) {
    String str = "abcabc123abc";

    char[] charArray = str.toCharArray();
    Stack<Character> stack = new Stack<>();
    StringBuilder newStr = new StringBuilder();

    for (char item : charArray) {
        stack.push(item);
    }

    for (int i = 0; i < charArray.length; i++) {
        newStr.append(stack.pop());
    }

    System.out.println("反转前:" + str);
    System.out.println("反转后:" + newStr.toString());
}

这样既可反转:漂亮

发布了117 篇原创文章 · 获赞 20 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/u010581811/article/details/105032171