io流练习

1io基础练习

字节流

复制代码
  1 package org.IOsummary;
  2 
  3 import javax.swing.*;
  4 import java.io.*;
  5 import java.nio.charset.Charset;
  6 import java.util.ArrayList;
  7 
  8 /**
  9  * 文件流:内存->文件,文件->内存的工具之一
 10  * 1.每种流怎么使用
 11  *
 12  */
 13 
 14 public class TestIO {
 15 
 16     /**
 17      * 流的类型
 18      * 1. Output/InPut 类型的流,字节(byte)流 范围是 0000 0000 - 1111 1111  也就是0 - 255
 19      *          文件输入/输出流 FileOutputStream/FileInputStream
 20      *          对象输入/输出流  ObjectOutputStream/ObjectInputStream
 21      * 2. Read/Write 类型的流,字符(char)流 范围是 0000 0000 0000 0000 - 1111 1111 1111 1111  也就是 0 -65535
 22      *          读文件 Read    写文件  Write
 23      *          FileRead FileWrite
 24      *
 25      */
 26 
 27     /**
 28      * 常见操作
 29      *
 30      */
 31 
 32     /**
 33      * 文件字节流常见错误和异常
 34      * 创建流-- 初始化建立流对象
 35      *          文件不存在--自动创建吗?(不创建/尝试创建)--目录不存在异常
 36      *                  1.读文件时候不可能给你创建
 37      *                  2.写文件时:1.重名2.父目录
 38      *          是否追加
 39      *              1不追加会把文件清空,重新写
 40      *              2只存在写文件,读文件不会清空,除非你打开它了。
 41      *                      不仅读文件而且写文件,需要在文件读完之后,实例化写的流
 42      * 使用流--
 43      *          连续读,已经结束了,无意义但是不会出错
 44      * 刷新流
 45      *          1.刷新写入的流,有缓冲的不刷新不会写。
 46      *          2.读的时候,就不用了,操作的时候不会影响。
 47      * 关闭流
 48      *      1.有自动关闭,
 49      *      2.自动关闭会刷新流
 50      */
 51     public static void test0(){
 52         File file = new File("d:/notfound");
 53         try (FileInputStream fileInputStream = new FileInputStream(file)){
 54 
 55         }
 56         catch (FileNotFoundException e){
 57             System.out.println("文件没找到,不能为您创建");
 58             throw new RuntimeException(e);
 59         }
 60         catch (IOException e){
 61             System.out.println("文件写入异常");
 62             throw new RuntimeException(e);
 63         }
 64     }
 65 
 66     public static void test00(){
 67         File file = new File("d:/notfound");
 68         file.mkdirs();
 69         try(FileOutputStream fos = new FileOutputStream(file,true)){
 70 
 71         }
 72         catch (FileNotFoundException e){
 73             System.out.println("写入文件未找到,尝试为您创建失败");
 74         }
 75         catch (IOException e){
 76 
 77         }
 78         file = new File("d:/notfound/notfound");
 79         try(FileOutputStream fos = new FileOutputStream(file,true)){
 80 
 81         }
 82         catch (FileNotFoundException e){
 83             System.out.println("写入文件未找到,尝试为您创建失败");
 84             throw new RuntimeException(e);
 85         }
 86         catch (IOException e){
 87 
 88         }
 89     }
 90     public static void test000(){
 91         File file = new File("d:/iosummary/test000.txt");
 92         file.getParentFile().mkdirs();
 93         try {
 94             file.createNewFile();
 95         } catch (IOException e) {
 96             throw new RuntimeException(e);
 97         }
 98         try(FileOutputStream fos = new FileOutputStream(file,true)){
 99             byte[] bytes = "io流练习".getBytes(Charset.defaultCharset());
100             fos.write(bytes);
101             fos.write("你好!中国".getBytes());
102             fos.write('\r');
103             fos.write('\n');
104             fos.write(98);
105             fos.write('\r');
106             fos.write('\n');
107             fos.flush();//及时刷新写的流,不刷新它不会写入文件,文件是空的,这个会刷新是因为文件最后会关闭
108         }
109         catch (FileNotFoundException e){
110             System.out.println("文件不存在,文件尝试创建失败");
111         }
112         catch (IOException e){
113             System.out.println("写入文件异常");
114         }
115 
116         try (FileInputStream fis = new FileInputStream(file)){
117             //一个一个的读
118             /**
119              * 小知识
120              * 为什么可以用short去存储int的-1,因为int里面的-1截一下也是short的-1
121              * 即   -1  = 1111 1111 1111 1111 = 1111 1111 1111 1111 1111 1111 1111 1111
122              * 同样 -2 = f f f e = 0xffff 0xfffe
123              * 但是强制类型转换不推荐
124              * 用int数据更大啊,一会可能有更多的字符
125              */
126             int flag;
127             /*
128              */
129 //            ArrayList<Byte> bytes = new ArrayList<>();//错了
130             //必须用到 length  还需要类型转换
131             byte[] bytes = new byte[(int)file.length()];
132             //用for循环 i是计数器
133             for (int i = 0 ,len;(len = fis.read())!=-1;i++){
134                 bytes[i] = (byte)(len);
135             }
136             //解码需要知道文件编码类型,当然了,就是我用java写的,它的类型就是默认类型,Charset.defaultCharset().name() UTF-8
137 //            System.out.println(new String(bytes,Charset.defaultCharset()));
138 //            int b = fis.read();可以继续读但是已经是文件结尾了
139         }
140         catch (FileNotFoundException e){
141             System.out.println("文件不存在");
142         }
143         catch (IOException e){
144             System.out.println("读文件失败");
145         }
146 
147         //一次读一群
148         try(FileInputStream fisInp = new FileInputStream(file)){
149 //            byte[] bytes = fisInp.readAllBytes();//全部读到,这个更好
150             byte[] bytes = new byte[1024];
151             int len;
152             String str = "";
153             while((len = fisInp.read(bytes))!=-1){
154                 //这种方式等同把文件分成多分,显然会有中文乱码
155                 //len是真实读的
156 //                str += new String(bytes,Charset.defaultCharset());
157                 str += new String(bytes, 0,len,Charset.defaultCharset());
158             }
159             System.out.println(str);
160         }
161         catch (FileNotFoundException e){}
162         catch (IOException e){}
163     }
164 
165     /**
166      * 序列化练习
167      * 1.确定是存储对象
168      * 2.需要实现java.io.Serializable接口,添加序列号 private static final long serialVersionUID = 8683452581122892189L;
169      *
170      * 异常:名字应该是 类初始化异常
171      * 本质原因:修改了类,之前存储的可能和这次修改有冲突
172      * 1.序列号不对
173      * 2.序列号对但是类型不对,类型没有
174      *
175      * 存储的时候一般是全部覆盖,
176      * 一般是一个list集合,类似数据库表对象
177      *
178      * 一个原则:内存使用,外存存储
179      */
180 
181     /**
182      * 字符流
183      * 问题:
184      * 1.字符流和字节流不匹配
185      *      1.在UTF-8编码中
186      *              一个中文字符,对应1个字符,3个字节
187      *      2.写的时候用GBK和UTF-8写出来的结果一样,
188      *              不论哪种编码,写的时候都是"中国"就行
189      *2.及时刷新
190      *      1.关闭时自动刷新
191      *
192      */
193     public static void test1(){
194         File file = new File("d:/iosummary/test1.txt");
195         file.getParentFile().mkdirs();
196         try {
197             file.delete();
198             file.createNewFile();
199         } catch (IOException e) {
200             throw new RuntimeException(e);
201         }
202         try (FileWriter fw = new FileWriter(file,true)){
203             byte[] temp = "中国".getBytes("GBK");
204             byte[] temp2 = "河南省".getBytes("UTF-8");
205             fw.write("中国");
206             fw.write("\r\n河南省");
207             fw.write("\r\n南阳市\r\n");
208             fw.write(new String(temp,"GBK"));
209             fw.write(new String(temp2,"UTF-8"));
210 //            fw.flush();
211         } catch (IOException e) {
212             throw new RuntimeException(e);
213         }
214         try (FileReader fileInputStream = new FileReader(file)){
215             while(fileInputStream.ready()){
216                 //这里需要类型转换一下 返回值同样是int类型 这里-1到0xffff -1不是一个实际字符
217                 System.out.print((char)fileInputStream.read());
218             }
219         }
220         catch (FileNotFoundException e){
221 
222         }
223         catch (IOException e){
224 
225         }
226     }
227     public static void test10(){
228         File file = new File("d:/iosummary/test1.txt");
229         try (FileInputStream fileInputStream = new FileInputStream(file)){
230             byte[] bytes = fileInputStream.readAllBytes();
231             System.out.println(new String(bytes,"UTF-8"));
232             System.out.println(new String(bytes,"GBK"));
233         }
234         catch (FileNotFoundException e){
235 
236         }
237         catch (IOException e){
238 
239         }
240     }
241     /**
242      * 缓冲流
243      * 1.添加了缓冲区的流
244      * 2.同样close和flush二者必须选一个
245      */
246     public static void test2(){
247         File file = new File("d:/iosummary/test2");
248         file.getParentFile().mkdirs();
249         try {
250             file.createNewFile();
251         } catch (IOException e) {
252             throw new RuntimeException(e);
253         }
254         try(BufferedWriter writer = new BufferedWriter(new FileWriter(file))){
255             //9*9 9*8
256             //8*8
257             for (int i = 9;i>0;i--){
258                 for (int j = i;j>0;j--){
259                     writer.write(i+"*"+j+"="+i*j+"\t");
260                 }
261                 writer.newLine();
262             }
263         }
264         catch (IOException e){
265 
266         }
267         try(BufferedReader reader = new BufferedReader(new FileReader(file))){
268             while(reader.ready()){
269                 System.out.println(reader.readLine());
270             }
271         }catch (FileNotFoundException e){
272 
273         }
274         catch (IOException e){
275 
276         }
277     }
278 
279     public static void test22(){
280         File file = new File("d:/iosummary/test2");
281         file.getParentFile().mkdirs();
282         try {
283             file.createNewFile();
284         } catch (IOException e) {
285             throw new RuntimeException(e);
286         }
287         try {
288             BufferedOutputStream writer = new BufferedOutputStream(new FileOutputStream(file));
289             writer.write("123123123123".getBytes());
290 //            writer.flush();
291 //            writer.close();
292         }catch (FileNotFoundException e){
293 
294         }
295         catch (IOException e){}
296         try {
297             BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
298             byte bytes[] = bis.readAllBytes();
299             System.out.println(new String(bytes));
300         }
301         catch (FileNotFoundException e){
302 
303         }
304         catch (IOException e){
305 
306         }
307     }
308     /**
309      * 文件字节流
310      */
311     public static void main(String[] args) {
312 //        test0();
313 //        test00();
314 //        test000();
315 //        test1();
316 //        System.out.println("------------------------------------------------------");
317 //        test10();
318 //        test2();
319         test22();
320     }
321 }
复制代码

2图片和图片流

2.1图片

复制代码
 1 package org.imgio;
 2 
 3 /**
 4  * 建立某种格式的图片
 5  *  1.内存中创建(不管文件是否存在) == 实例化/其它
 6  *  2.在外存中保存
 7  */
 8 
 9 import javax.imageio.ImageIO;
10 import java.awt.image.BufferedImage;
11 import java.io.File;
12 import java.io.IOException;
13 
14 /**
15  * 基本图像格式
16  * 图片流:BufferedImage类
17  * RGB真彩图像 TYPE_INT_RGB
18  * 灰色图像 TYPE_BYTE_GRAY
19  * 透明画布 TYPE_INT_ARGB
20  */
21 
22 public class TextImageType {
23     /**
24      * 灰度图片
25      * 需要文件类型支持灰度
26      * 默认是黑色画布
27      */
28     public static void testGrey(){
29         int width = 200;
30         int height = 150;
31         int type = BufferedImage.TYPE_BYTE_GRAY;
32         BufferedImage img = new BufferedImage(width, height,type);
33         try {
34             ImageIO.write(img,"png",new File("GRAY.png"));
35             ImageIO.write(img,"jpg",new File("GRAY.jpg"));
36             ImageIO.write(img,"gif",new File("GRAY.gif"));
37         } catch (IOException e) {
38             throw new RuntimeException(e);
39         }
40     }
41     /**
42      * RGB真彩图片
43      * 需要文件类型支持RGB
44      * 默认是黑色画布
45      */
46     public static void testRGB(){
47         int width = 200;
48         int height = 150;
49         int type = BufferedImage.TYPE_INT_RGB;
50         BufferedImage img = new BufferedImage(width, height,type);
51         try {
52             ImageIO.write(img,"png",new File("rgb.png"));
53             ImageIO.write(img,"jpg",new File("rgb.jpg"));
54             ImageIO.write(img,"gif",new File("rgb.gif"));
55         } catch (IOException e) {
56             throw new RuntimeException(e);
57         }
58     }
59     /**
60      * 透明画布
61      * 需要文件类型支持ARGB
62      * 默认是透明画布
63      * jpg不支持,创建不了;返回值为false
64      */
65     public static void testARGB(){
66         int width = 200;
67         int height = 150;
68         int type = BufferedImage.TYPE_INT_ARGB;
69         BufferedImage img = new BufferedImage(width, height,type);
70         //写入外存
71         try {
72             ImageIO.write(img,"png",new File("ARGB.png"));
73             System.out.println(ImageIO.write(img, "jpg", new File("ARGB.jpg")));
74             ImageIO.write(img,"gif",new File("ARGB.gif"));
75         } catch (IOException e) {
76             throw new RuntimeException(e);
77         }
78     }
79     public static void main(String[] args) {
80         testGrey();
81         testARGB();
82         testRGB();
83     }
84 }
复制代码

2.2画图基本操作

复制代码
  1 package org.imgio;
  2 
  3 import javax.imageio.ImageIO;
  4 import java.awt.*;
  5 import java.awt.image.BufferedImage;
  6 import java.io.*;
  7 import java.util.HashMap;
  8 import java.util.Map;
  9 
 10 /**
 11  * 画一个图片
 12  * 新建(Draw1)和追加(Draw2)
 13  */
 14 
 15 public class TestDrawImg {
 16     /**
 17      * 拷贝图片并添加文字
 18      *
 19      * 1.文件格式 1:RGB; 2:ARGB;10GREY
 20      * 2.内存默认图片格式
 21      * 3.拿到内存图片的画笔--画笔构造方法是保护的,我们不实例化
 22      * 4.使用画笔将另一个图片画入
 23      * 5.使用画笔将字符串画入
 24      *      可以设置字符串颜色,
 25      *         //new Color(156, 156, 156, 255);RGBA的值 A越大越不透明
 26      *         //new Color(255);  RGBA设置颜色 8位差分 前八位 透明度, 接着红色,绿色,蓝色
 27      *         其它颜色变为灰白色规则
 28      *              三个值相同,1-224都是灰色,但是值越小越接近黑色,值越大,越接近白色。
 29      *                  使用取色板可以取一下
 30      *
 31      * 6.将内存文件写入磁盘
 32      */
 33     public static void testDraw1(){
 34         File imgFile = new File ("pic\\day28/pic5.jpg");//目标文件
 35         BufferedImage img=null;
 36         int width=0,height=0;
 37         try {
 38             img = ImageIO.read(imgFile);
 39             width = img.getHeight();
 40             height = img.getWidth();
 41             System.out.println(width+" "+height);
 42         }
 43         catch (IOException e){
 44             throw new RuntimeException(e);
 45         }
 46         BufferedImage bufferedImage = new BufferedImage(width,height,10);//内存图片
 47 
 48         Graphics2D g = bufferedImage.createGraphics();
 49 
 50         g.drawImage(img, 0,0,null);
 51 
 52         Color color = new Color(120, 120, 120);
 53         g.setColor(color);
 54         g.drawString("13782557165",50,50);
 55 
 56         try {
 57             ImageIO.write(bufferedImage,"png",new File("./pic/day28/draw1.png"));
 58         } catch (IOException e) {
 59             throw new RuntimeException(e);
 60         }
 61     }
 62     /**
 63      * 错误点
 64      * 1.读的时候认为文件不是图片,返回为null.
 65      *          错误代码:File file = new File("./pic/day28/pic.txt");File file = new File("./pic/day28/pic4.webp");
 66      * 2.路径不能写错,特别是相对路径
 67      *          当前目录是工作目录,也是项目目录,但是它不是java包路径 package
 68      *          错误代码:如果coding为打开目录 ../pic/day28/pic4.webp"错误
 69      *          反之如果day28为打开目录./pic/day28/pic4.webp错误
 70      * 3.不熟练
 71      * Graphics2D(绘图);bufferedImage(缓冲文件);ImageIO(图片输入输出)
 72      * 4.画的时候,彩色变为灰白色, 图片颜色变了,字体颜色变了
 73      */
 74 
 75     /**
 76      * 在源图片中添加水印
 77      * 1.将图片读入内存
 78      * 2.得到长宽属性
 79      * 3.得到画笔,
 80      * 4.设置画笔格式和颜色
 81      * 5.画字符串,
 82      * 6.保存
 83      */
 84     public static void testDraw2(){
 85         File file = new File("./pic/day28/pic.jpg");
 86         BufferedImage bufferedImage = null;
 87         try {
 88             bufferedImage = ImageIO.read(file);
 89         } catch (IOException e) {
 90             throw new RuntimeException(e);
 91         }
 92         if(bufferedImage==null){
 93             System.out.println("图片不能识别,");
 94         }
 95 
 96         Graphics2D graphics2D = bufferedImage.createGraphics();
 97 
 98         String text = "版权所有 13782557165";
 99 
100         Color color = new Color(233, 245, 230,255);
101 
102         //水印文字的坐标位置
103         int weight = 100;
104         int height = 200;
105         //控制字体格式
106         //系统中有的
107         Font font = new Font("宋体",Font.BOLD,30);
108         //保存字体设置
109         graphics2D.setFont(font);
110         //保存颜色设置
111         graphics2D.setColor(color);
112 
113         graphics2D.drawString(text,weight,height);
114 
115         try{
116             ImageIO.write(bufferedImage,"jpg",new File("./pic/day28/gt.jpg"));
117         }
118        catch (IOException e){
119 
120        }
121     }
122     /**
123      * Draw1和Draw2比较
124      * 相同点,都是图像处理,处理方法都差不多
125      * 不同点,处理的文件不同。
126      *      Draw1是在内存中新建图片,我们通过new实例化
127      *      Draw2是读文件然后将内存地址拿到并赋值。
128      *
129      * 画图更加清晰了
130      * 图片处理就是将图片读入内存,然后在存入外存。或者直接在内存中写,然后存入外存。
131      */
132 
133     /**
134      * 清除锯齿和文件定位
135      */
136     public static void testDraw3(){
137         //缓冲图片和原图片
138         File file = new File("./pic/day28/pic1.jpg");
139         BufferedImage bufferedImage;
140         try {
141             bufferedImage = ImageIO.read(file);
142         } catch (IOException e) {
143             throw new RuntimeException(e);
144         }
145 
146         //画笔graphics
147         Graphics2D graphics2D = bufferedImage.createGraphics();
148         graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
149         graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
150         graphics2D.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_DEFAULT);
151         Map<RenderingHints.Key,Object> map = new HashMap<>();
152 //        Map<Object,Object> map = new HashMap<>();
153 //        map.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
154 //        map.put(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
155 //        map.put(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_DEFAULT);
156 //        graphics2D.setRenderingHints(map);
157         String text = "纸上得来终觉浅,绝知此事要躬行。";
158         Color color = Color.RED;
159         graphics2D.setColor(color);
160         Font font = new Font("宋体",Font.BOLD,30);
161         graphics2D.setFont(font);
162         graphics2D.drawString(text,50,50);
163         graphics2D.fillOval(200,200,100,100);
164         graphics2D.drawOval(500,500,200,100);
165         //目标图片
166         try{
167            ImageIO.write(bufferedImage,"jpg",new File("./Draw3.jpg"));
168         }
169         catch (IOException e){
170             System.out.println("保存失败");
171         }
172     }
173 
174     public static void draw4(){
175         BufferedImage bufferedImage = new BufferedImage(1000,1000,1);
176         Graphics2D graphics2D = bufferedImage.createGraphics();
177 //        graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
178 //        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
179 //        graphics2D.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_DEFAULT);
180 
181         Map<RenderingHints.Key,Object> map = new HashMap<>();
182         map.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
183         map.put(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
184         map.put(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_DEFAULT);
185         graphics2D.setRenderingHints(map);
186         graphics2D.fillOval(100,200,200,300);
187         graphics2D.setStroke(new BasicStroke(20f));
188         graphics2D.setColor(getRandomRGB());
189         graphics2D.drawOval(500,200,200,300);
190         graphics2D.setColor(getRandomRGB());
191         graphics2D.drawOval(550,200,200,300);
192         graphics2D.setColor(getRandomRGB());
193         graphics2D.drawOval(600,200,200,300);
194         try {
195             ImageIO.write(bufferedImage,"jpg",new File("draw4.jpg"));
196         }catch (IOException e){
197 
198         }
199     }
200     /**
201      * 易错点
202      * Map map = new HashMap<>(); 和Map<RenderingHints.Key,Object> map = new HashMap<>();的区别
203      *          1.前者是万能的,等同于Map<Object,Object>map = new HashMap<>();比较灵活,可放任何对象
204      *          2.前者编译时不会提示类型不匹配
205      *          3.前者是作为Object的实现类使用,后者是RenderingHints.Key的实现类使用
206      *                  toString方法
207      *                  RenderingHints.Key独有方法不知道啊  这里是独有方法
208      *          4.如果不知道类型那么用前者,知道类型用后者较好。
209      *          5.用泛型可以存储,可以表示数据结构
210      *          6.这里不能用Object
211      *
212      */
213 
214     //得到一个随机RGBA颜色
215     public static Color getRandomRGBA(){
216         int red = (int)(Math.random()*256);
217         int green = (int)(Math.random()*256);
218         int blue = (int)(Math.random()*256);
219         int alpha = (int)(Math.random()*256);
220         return new Color(red,green,blue,alpha);
221     }
222     //得到一个随机RGB颜色
223     public static Color getRandomRGB(){
224         return new Color((int)(Math.random()*0x01000000));
225     }
226     /**
227      * 随机性
228      *  总而言之就是一个数据,
229      *  前者是随机控制三原色,后者是随机值,后者不能做到三原色随机,但是也是随机颜色
230      *  前者随机性更好
231      */
232     
233     public static void main(String[] args) {
234 //        testDraw1();//复制图片
235 //        testDraw2();//在原图片上添加
236 //        testDraw3();
237         draw4();
238     }
239 
240 }
复制代码

2.3画图补充练习

 

复制代码
  1 package org.imgio;
  2 
  3 import com.google.zxing.*;
  4 import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
  5 import com.google.zxing.client.j2se.MatrixToImageWriter;
  6 import com.google.zxing.common.BitMatrix;
  7 import com.google.zxing.common.HybridBinarizer;
  8 import com.google.zxing.qrcode.QRCodeReader;
  9 import com.google.zxing.qrcode.QRCodeWriter;
 10 import com.google.zxing.qrcode.encoder.QRCode;
 11 import org.jsoup.Jsoup;
 12 
 13 import javax.imageio.ImageIO;
 14 import javax.swing.*;
 15 import java.awt.*;
 16 import java.awt.image.BufferedImage;
 17 import java.awt.image.ImageObserver;
 18 import java.io.File;
 19 import java.io.FileNotFoundException;
 20 import java.io.IOException;
 21 import java.util.*;
 22 import java.util.List;
 23 
 24 public class TestOther {
 25     /**
 26      * 描述:实现java程序自动打开文件
 27      * cmd start指令可以打开
 28      * 1.不能执行路径有空格的程序
 29      *
 30      * 直接写路径名的
 31      * 可运行的程序或批处理文件。
 32      */
 33     //用java程序自动打开百度网页
 34 
 35     /**
 36      * 不等于开机启动
 37      */
 38     public static void test() {
 39         //程序启动打开百度
 40         String url = "http://www.baidu.com";
 41         Runtime run = Runtime.getRuntime();
 42         //相当于在命令行输入 start指令
 43         //注意:空格分隔
 44         try {
 45 //            run.exec("\"C:\\Program Files (x86)\\Tencent\\QQ\\Bin/qq.exe\"");
 46             run.exec("\"C:\\Program Files (x86)\\Tencent\\WeChat\\wechat.exe\"");
 47 //            run.exec("\"C:\\Program Files (x86)\\Tencent\\WeChat\\微信.exe\"");//支持中文,必须是可执行和批处理
 48 //            run.exec("cmd /k start http://www.baidu.com");
 49             run.exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" draw4.jpg");
 50             //只有火狐浏览器支持相对路径
 51         } catch (IOException e) {
 52             throw new RuntimeException(e);
 53         }
 54     }
 55     /**
 56      * 文件资源定位符(文件没有放到网上,在我们本地)
 57      * file:///文件路径
 58      * file:///C:/Users/28700/Pictures/Saved%20Pictures/2054727.jpg 1是一个超链接,可以点击
 59      * 浏览器是帮我们补充了,类似还有 www.baidu.com
 60      */
 61 
 62     /**
 63      * Color颜色对象使用
 64      * 画图:可以控制画笔颜色画东西
 65      * 如画字符串,画图形,拷贝应该也是有颜色的(对应颜色转换)
 66      * 初始化
 67      * 颜色对象:代表了一个颜色
 68      * 使用某一种颜色(是一个对应的rgb常量)
 69      * RGB:第一个表示红色值是多少,第二个绿色值是多少,第三个蓝色值是多少
 70      * 1如果是红色,是 255,0,0;红色值满的是鲜红
 71      * 2如果是白色,是 255,255,255 特殊的颜色
 72      * 3如果是黑色,是 0,0,0 特殊的颜色
 73      * 4灰白色是三个值相等,不为0,0,0的颜色,值越小越接近黑色,值越大越接近白色
 74      * 5还有就是颜色合成,红+绿=黄色,红色绿色值越大黄色颜色会变深
 75      * RGBA:在RGB基础上添加了透明度
 76      * 1.A值越小越透明,
 77      * 2.用一个int表示 16位的更好操作
 78      * 3.前8位透明度 接着是红色 然后是绿色 最后是蓝色
 79      * <p>
 80      * 使用(设置颜色)
 81      */
 82     public static void testColor() {
 83         BufferedImage bufferedImage = new BufferedImage(1000, 1000, 1);
 84         Graphics2D graphics2D = bufferedImage.createGraphics();
 85 
 86 
 87         Color color = Color.WHITE;
 88         color = new Color(255, 255, 0);
 89         color = new Color(200, 200, 0);
 90 
 91         color = new Color(0, 0, 0, 0);
 92         color = new Color(0xff0000ff);
 93         graphics2D.setColor(color);
 94     }
 95 
 96     /**
 97      * 字体Font:
 98      * 画图的时候,需要画字符串,字符串就是字体内容,java通过设置字体格式控制画的字符串样式
 99      * 1.字体类型
100      * 1.系统中的所有字体
101      * 2.系统默认字体
102      * 2.字体格式:0-2 常规(0),加粗(1),斜体(2), driveFont(int)
103      * 3.字体大小 driveFont(float)
104      * 默认字体样式,我们其实都是在修改样式
105      * 加载外部字体(感觉有很多问题)
106      * 文字控制--用一种系统字体就好了
107      * 画布透明在网页上不会把背景给挡着
108      * 还有就是有些外部字体不能表示所有中文
109      * 初始化Font时候字体大小是int类型,但是deriveFont类型是int,大小是float 小建议就是 类型用byte 大小是int; 这就是设计好的
110      */
111     public static void testFont1() {
112         //灰度图片--背景黑色,颜色默认白色
113         BufferedImage bufferedImage = new BufferedImage(1000, 1000, 10);
114         //        Graphics2D graphics2D = bufferedImage.getGraphics();
115         Graphics2D graphics2D = bufferedImage.createGraphics();
116 //普通画笔设计
117         Color color = new Color(233, 245, 230);
118         graphics2D.setColor(color);
119 
120         graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
121         String text = "系统字体";
122         //字体的横纵坐标x,y 不归字体管,实际是画笔管
123         int x = 30, y = 30;
124         graphics2D.drawString(text, x, y);
125 
126         //控制字体效果
127         Font font = new Font("楷体", Font.ITALIC, 30);
128 
129         //画笔设置字体样式
130         graphics2D.setFont(font);
131 
132         graphics2D.drawString(text, 100, 100);
133         //保存
134         try {
135             ImageIO.write(bufferedImage, "png", new File("other.png"));
136             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" " + "other.png");
137         } catch (IOException e) {
138             System.out.println("内存写入磁盘异常");
139             throw new RuntimeException(e);
140         }
141     }
142 
143     public static void testFont2() {
144         BufferedImage bufferedImage = new BufferedImage(1000, 1000, 10);
145         Graphics2D graphics2D = bufferedImage.createGraphics();
146         Color color = new Color(233, 245, 230);
147         graphics2D.setColor(color);
148         graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
149         String text = "外部字体";
150         int x = 30, y = 30;
151         graphics2D.drawString(text, x, y);
152         //建立加载外部文件
153         Font font = null;
154         try {
155             //设置真显格式支持TTF字体文件
156             //真显格式:
157             font = Font.createFont(Font.TRUETYPE_FONT, new File("./font/经典楷体简.TTF"));
158             //控制字号-- 也可以用样式(3个值) --- font自己本身不变,拷贝
159             font = font.deriveFont(30f);
160             font = font.deriveFont(1);
161         } catch (FontFormatException e) {
162             throw new RuntimeException(e);
163         } catch (IOException e) {
164             throw new RuntimeException(e);
165         }
166         graphics2D.setFont(font);
167         graphics2D.setColor(color);
168         graphics2D.drawString(text, 100, 100);
169         try {
170             ImageIO.write(bufferedImage, "png", new File("other.png"));
171             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" " + "other.png");
172         } catch (IOException e) {
173             System.out.println("内存写入磁盘异常");
174             throw new RuntimeException(e);
175         }
176     }
177 
178     /**
179      * 1.拿到字体样式的高,字符串的长度
180      * 使用FontMetrics类 并不是我们实例化的,是画笔实例化的
181      * getFontMetrics() 类似 createGraphics()
182      * 获取字符串的宽度 stringWidth
183      * 获取字体的高度 getAscent
184      * 注意:避免字符串太长了:只有一行的
185      * 2、字符串定位规则。
186      * 1.是在左下角的位置开始画字符串
187      * (0.0)开始字体会写在画的上方
188      * 2.水平坐标增加是向右移动;垂直坐标增加是向下移动;坐标轴比较特殊
189      * 案例:
190      * 水平居中:(imgWidth-stringWidth)/2 , (imgHeight+fontHeight)/2
191      * 右下角位置 imgWidth - stringWidth -10  , imgHeight -10;
192      * 左上角位置 10 , fontHeight +10
193      */
194     public static void testFont3() {
195         //画布宽高
196         int imgWidth = 600;
197         int imgHeight = 220;
198         //几个字 没有用
199         int len = 3;
200         BufferedImage img = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_ARGB);
201         Graphics2D pen = img.createGraphics();
202         Font font = new Font("楷体", 1, 30);
203         Color c = new Color(0x0fffafef);
204         pen.setColor(c);
205         pen.setFont(font);
206         String text = "刘高源";
207 
208         //从画笔对象中获得指定的font对象的FontMetrics
209         FontMetrics fm = pen.getFontMetrics(font);
210 
211         //获得字符串宽度
212         int stringWidth = fm.stringWidth(text);
213         //搞定水平居中
214         // +imgwidth/2(画布中间)
215         //减少 stringWidth/2  字符串开始
216         int x = imgWidth / 2 - stringWidth / 2;
217         x = (imgWidth - stringWidth) / 2;
218 
219         //获得字符串高度--这并不是字符串高度
220         int fontHeight = fm.getAscent();
221         //水平居中
222         int y = (imgHeight - fontHeight) / 2;
223         //发现偏移的不对,
224 
225         y = imgHeight / 2;
226 
227 //        pen.drawString(text,x,y);
228         //找到中间位置
229         pen.setColor(new Color(0));
230         //两点确定一条直线
231         //水平中间线
232         pen.drawRect(0, imgHeight / 2 + 1, imgWidth, imgHeight / 2 + 1);
233         //在水平线上方,说明高度有点低
234         y = imgHeight / 2 + fontHeight;
235 //        pen.drawString(text,x,y);
236 
237         //恰好发现直线就是对称线下方
238         y = imgHeight / 2 + 1 + fontHeight / 2;
239         y = (imgHeight + fontHeight) / 2;
240 
241         //中间
242         pen.setColor(c);
243 //        pen.drawString(text,x,y);
244         //右下角
245         x = imgWidth - fm.stringWidth(text) - 10;
246         y = imgHeight - 10;
247         pen.drawString(text, x, y);
248         //左上角
249         x = 10;
250         y = fontHeight + 10;
251         pen.drawString(text, x, y);
252 
253         //使用一下Height测试英文 发现 相对于Ascent , Height太大了
254         //英文相对汉字偏下一些
255         fontHeight = fm.getHeight();
256         text = "张三abcdefg";
257         stringWidth = fm.stringWidth(text);
258         x = (imgWidth - stringWidth) / 2;
259         y = (imgHeight + fontHeight) / 2;
260         pen.drawString(text, x, y);
261         //结果 getHeight也控制不了英文
262         try {
263 //            ImageIO.write(img,"png","drawfont3.png");
264             ImageIO.write(img, "png", new File("drawfont3.png"));
265             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" drawfont3.png");
266         } catch (IOException e) {
267             e.printStackTrace();
268         }
269     }
270 
271     /**
272      * 所有系统字体
273      */
274     public static List getSystemFont() {
275         java.util.List<String> list = new ArrayList<>();
276         GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
277         for (Font font : e.getAllFonts()) {
278             list.add(font.getName());
279         }
280         return list;
281     }
282 
283 
284     /**
285      * 实战:二维码基础
286      * 一、写二维码
287      * 功能
288      * 1.将字符串变为图片:看一下字符串内容
289      * 2.将网址变为图片:访问网址(地址)--这个需要联网
290      * 3.将tel变为图片:打电话
291      * 4。.apk扫码下载
292      * 特点:
293      * 1.不同的应用扫码结果不同,因为关系到他们的规划,总而言之二维码本质就是字符串
294      * 2.怎么生成二维码
295      * 导入google二维码组件(模块依赖)jar,
296      * 导入类QRCodeWriter并实例化对象
297      * 实例化类的encode方法能将字符串编成一个图片存起来
298      * 24,10 10:40
299      *
300      * 生成二维码方法步骤:
301      * 设置二维码内容(可以是中文)  String
302      * 设置编码样式Map集合  Map<EncodeHintType,String>
303      * 得到编码  BitMatrix(位矩阵)   QRCodeWriter().encode方法
304      * 将编码变为图片   MatrixToImage的toBufferedImage 将 位矩阵变为 图片BufferedImage
305      * 将图片存入外存/输出
306      * 其它问题:
307      * 1.中文乱码
308      * 2.二维码不在乎颜色,有检错,有3个角,矩阵Matrix
309      */
310     public static void testQr() {
311         //二维码内容
312         String homePage = "http://192.168.16.13:8080/liu11/2054232.jpg";
313         try {
314             BitMatrix bitMatrix = new QRCodeWriter().encode(homePage, BarcodeFormat.QR_CODE, 400, 400, null);
315             BufferedImage img = MatrixToImageWriter.toBufferedImage(bitMatrix);
316             ImageIO.write(img, "png", new File("qr.png"));
317             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" qr.png");
318         } catch (WriterException e) {
319             throw new RuntimeException(e);
320         } catch (IOException e) {
321 
322         }
323     }
324 
325     public static void testQr2(){
326         //中文乱码;底层是byte[]
327         String chinese = "姓名:刘高源";
328         Map<EncodeHintType,String> hints = new HashMap<>(1);
329         hints.put(EncodeHintType.CHARACTER_SET,"utf-8");
330         try {
331             BitMatrix bitMatrix = new QRCodeWriter().encode(chinese,BarcodeFormat.QR_CODE,400,400,hints);
332             BufferedImage img = MatrixToImageWriter.toBufferedImage(bitMatrix);
333             ImageIO.write(img,"png",new File("liugaoyuan.png"));
334             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" liugaoyuan.png");
335         }
336         catch (WriterException e) {
337 
338         }
339         catch (IOException e) {
340 
341         }
342     }
343     public static void testQr3(){
344         String tel = "tel://13782557165";
345         try {
346             BitMatrix bitMatrix = new QRCodeWriter().encode(tel,BarcodeFormat.QR_CODE,400,400);
347             BufferedImage img = MatrixToImageWriter.toBufferedImage(bitMatrix);
348             ImageIO.write(img,"png",new File("tel.png"));
349             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" tel.png");
350         }
351         catch (WriterException e) {
352 
353         }
354         catch(IOException e){
355 
356         }
357     }
358 
359 
360     //二、二维码解析==读二维码
361     //检查一个图里面有没有二维码
362     public static void testQr4(){
363         try {
364 //            BufferedImage img = ImageIO.read(new File("draw31.jpg"));
365             BufferedImage img = ImageIO.read(new File("qrthree.png"));
366 //            BufferedImage img = ImageIO.read(new File("draw3.txt"));
367 //            BufferedImage img = ImageIO.read(new File("draw3.jpg"));
368             BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(img);
369             //二进制解析器
370             HybridBinarizer hybridBinarizer = new HybridBinarizer(source);
371             BinaryBitmap bitmap = new BinaryBitmap(hybridBinarizer);
372             Result result = new QRCodeReader().decode(bitmap);
373             if (result.getText()!=null){
374                 System.out.println(result.getText());
375             }
376             else{
377                 System.out.println("没有找到二维码");
378             }
379         }
380         catch (IOException e) {
381             System.out.println("没有此文件,文件非图片不可读");
382             throw new RuntimeException(e);
383         } catch (ChecksumException e) {
384             System.out.println("图片中二维码数量过多");
385             throw new RuntimeException(e);
386         } catch (NotFoundException e) {
387             System.out.println("图片中没有找到二维码");
388             throw new RuntimeException(e);
389         } catch (FormatException e) {
390             System.out.println("图片中没有二维码3");
391             throw new RuntimeException(e);
392         }
393     }
394 
395     public static void test11(){
396         //将多张个图片和成一个
397         BufferedImage image = new BufferedImage(1000,1000,2);
398         try {
399             BufferedImage img = ImageIO.read(new File("liugaoyuan.png"));
400             Graphics2D pen = image.createGraphics();
401             pen.drawImage(img, 0,0,400,400, null);
402             img = ImageIO.read(new File("qr.png"));//这个位置的二维码先被识别
403             pen.drawImage(img, 450,0,400,400, null);
404             img = ImageIO.read(new File("tel.png"));
405             pen.drawImage(img, 0,450,400,400, null);
406             ImageIO.write(image,"png",new File("qrthree.png"));
407             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" qrthree.png");
408         }
409         catch (IOException e) {
410             System.out.println("文件没有找到,文件读失败");
411         }
412     }
413     /**
414      * 错误点,
415      * 读的图片和写的是同一个,造成问题。
416      * 正确做法应该新建一个图片
417      */
418 
419     /**
420      * 思路:编写一个二维码工具类,getQrCode()方法实现生成二维码
421      *
422      * 如何让别人扫描访问自己的电脑资源
423      * 1.自己建服务器 java18可以,tomcat可以,内部都有服务器
424      *      java18 代码 jwebserver -b 0.0.0.0 -p 80
425      * 2.别人和你在同一个局域网,或者都连接了互联网,WiFi热点等能访问你
426      *
427      * 3.资源部署到服务器的网上
428      *          资源的路径是c:/share/share.png。服务器应该在share/c盘上部署
429      *
430      */
431     public static void getQrCode(int w,int h,String text){
432         File file = new File("c:/share/myshare.png");
433         if (!file.getParentFile().isDirectory()){
434             file.getParentFile().mkdirs();
435         }
436         //支持中文
437         Map<EncodeHintType,String> hints = new HashMap<>();
438         hints.put(EncodeHintType.CHARACTER_SET,"UTF-8");
439         try {
440             BitMatrix bitMatrix =new QRCodeWriter().encode(text,BarcodeFormat.QR_CODE,w,h,hints);
441             BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
442 
443             ImageIO.write(image,"png",file);
444             Runtime.getRuntime().exec(" \"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" "+file.getAbsolutePath());
445         }
446         catch (IOException e){
447 
448         }
449         catch (WriterException e){
450 
451         }
452 
453 
454     }
455     /**
456      * 输入然后生成相应翻译图片
457      * 1.二维码内容过多太密集可能无法表达
458      * 2.在电脑上上输入,手机扫描,有点不方便
459      */
460 
461     public static void getInfo(){
462         String w = JOptionPane.showInputDialog("请输入词汇");
463         String u = String.format("https://youdao.com/w/eng/%s/#keyfrom=dict2.index",w);
464 
465         try {
466             String t = Jsoup.connect(u).get().select("div[class=trans-container]").get(0).text();
467             System.out.println(w+":"+t);
468             //翻译结果生成二维码:
469             getQrCode(400,400,w+":"+t);
470         }
471         catch (Exception e){
472             e.printStackTrace();
473         }
474 
475     }
476 
477     /**
478      * 实战:验证码基础
479      * 验证码原理:
480      * 功能:为了防止网络暴力破解
481      * 一闪一闪的,多张图片合成的
482      *      人都容易看错的验证码,好的验证码
483      *      难度级别随意调
484      * 验证码是通过会话机制走的,每个人每次登陆都不同,都需要验证
485      *
486      * 思路:建立一个图像,随机写一个字符串,图片保存下来,
487      * (将图片的字符串,保存到session会话中,和表单提交的验证码验证)
488      *
489      * 得到图像属性:宽高字体个数,一个字体宽度,字体高度
490      * 一个一个随机输出字体,应该保证一定顺序(之后验证)
491      */
492     public static void testcoding(){
493         String letter = "abcdefghijklmnopqrstuvwsyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
494         int imgWidth = 160;
495         int imgHeight = 60;
496         int len= 4;
497         BufferedImage img = new BufferedImage(160,60,2);
498 
499         Graphics2D pen = img.createGraphics();
500 
501         FontMetrics metrics = pen.getFontMetrics();
502         int sh = metrics.getAscent();
503         int sw = metrics.stringWidth("a");
504         String text;
505         int width = imgWidth/len;
506         pen.setFont(new Font("",1,30));
507         for (int i = 0,x = 20;i<len;i++){
508             int y = (int)(Math.random()*(imgHeight-sh)) + sh +5;
509             text = String.valueOf( letter.charAt((int)(Math.random()*62)));
510             pen.setColor(new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*100)+100));
511             pen.drawString(text,x,y);
512             System.out.print(text);
513             x+=width;
514         }
515         //添加干扰
516         int l = 50;
517         for (int i = 0,x,y;i<l;i++){
518             x = (int)(Math.random()*(imgWidth));
519             y = (int)(Math.random()*(imgHeight));
520             text = String.valueOf( letter.charAt((int)(Math.random()*62)));
521             pen.setColor(new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*50)));
522             pen.setFont(new Font("楷体",2,(int)(Math.random()*20)));
523             pen.drawString(text,x,y);
524         }
525         //添加正弦干扰线,弯曲的线
526         //在字体后面添加会覆盖字体,增加识别难度
527         //斜率不同 根据图片高度控制这里0-1合适
528         boolean flag = true;
529         pen.setColor(new Color(0xff543));
530         pen.setStroke(new BasicStroke(5f));
531         for (int x=0,y = imgHeight/2,k;x<imgWidth;){
532             k = (int)(Math.random()*(2));
533             if (flag){
534                 pen.drawLine(x,y,x+1,y-=k);
535                 y-=2*k;
536                 if (y<imgHeight/4){
537                     flag = false;
538                 }
539             }
540             else{
541                 pen.drawLine(x,y,x+1,y+=k);
542                 y+=2*k;
543                 if (y>imgHeight/4 *3){
544                     flag = true;
545                 }
546             }
547             x+=2;
548         }
549         try {
550             ImageIO.write(img,"png",new File("coding1.png"));
551             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" coding1.png");
552         }
553         catch(IOException e){
554             System.out.println("IO异常");
555         }
556     }
557     /**
558      * 锦上添花:
559      * 1.字体的颜色,字体的样式容易忘记设置
560      *          1.是每次随机(每个字都可能不同)还是都一样(每个字都一样)
561      *
562      * 2.干扰
563      *       1.添加字体
564      *       2.选择某种颜色的字体
565      *       3.干扰线
566      *
567      * 3.提示我说Math.random可以取到0,并且获得随机整数应该用Random
568      */
569 
570     /**
571      * 基本图形
572      * 1.图形类型
573      * 基础图形:
574      * 矩形:rect->正方向,边框
575      * 椭圆:oval->圆
576      * 直线:line->对角线(斜率),虚线
577      * 进阶图形
578      * roundRect->圆,椭圆
579      * arc->圆,扇形,椭圆
580      * 2.图形颜色
581      * 就是通过画笔颜色
582      * 3.粗细
583      * BasicStroke对象
584      * 4.定位
585      *      1.左上角开始
586      *      2.width,height是图形宽高
587      *      3.中心位置公式 (x+width/2,y+height/2)
588      * 5.填充(fill)/不填充(draw)
589      */
590     public static void testFigures() {
591         int imageWidth = 660;
592         int imageHeight = 220;
593         BufferedImage img = new BufferedImage(imageWidth, imageHeight, 2);
594         Graphics2D pen = img.createGraphics();
595 
596         Color c = new Color(0xffaaaafa);
597 
598         int k = imageWidth / (imageHeight);
599         int x = 0, y = 0;
600         //多条线组成的实线
601         for (;x<imageWidth&&y<imageHeight;){
602             pen.drawLine(x,y,x+k,y+1);
603             x+=k;
604             y++;
605         }
606 //        //虚线过度
607 //        for (int i =1;x<imageWidth&&y<imageHeight;i++){if ((i&1)==1){System.out.println(i);pen.drawLine(x,y,x+k,y+1);}x+=k;y++;}
608         x = imageWidth;
609         y = 0;
610         while (x>0&&y<imageHeight) {
611             pen.drawLine(x, y, x - k, y + 1);
612             x -= 2 * k;
613             y += 2;
614         }
615 
616         //矩形
617         //位置:是在左上角开始
618         pen.fillRect(0, 0, 50, 50);
619         pen.fillRect(50, 50, 50, 50);
620 
621         //不填充
622         pen.drawRect(100, 0, 50, 50);
623 
624         //
625         pen.drawOval(150, 50, 50, 50);
626         pen.fillOval(200, 0, 50, 50);
627         //椭圆
628         pen.fillOval(250, 50, 25, 50);
629         pen.fillOval(300, 0, 50, 25);
630 
631         //圆角矩形
632         //可以画椭圆和圆
633         pen.drawRoundRect(350, 50, 50, 25, 50, 25);
634         pen.fillRoundRect(400, 0, 50, 50, 50, 50);
635         pen.fillRoundRect(450, 50, 50, 25, 50, 24);
636 
637         //设置线条粗细(宽度)
638         BasicStroke bs = new BasicStroke(15f);
639         pen.setStroke(bs);
640         pen.drawRoundRect(500, 0, 50, 25, 50, 25);
641         //没有消除棱角
642         try {
643             ImageIO.write(img, "png", new File("Figures.png"));
644             Runtime.getRuntime().exec("\"C:/Program Files/Mozilla Firefox/firefox.exe\" Figures.png");
645         } catch (IOException e) {
646 
647         }
648     }
649     /**
650      * 双鱼线实战
651      * 1.后面的可以将前面的替代了
652      * 2.开始并不是圆心
653      *         圆心坐标公式(x+width/2,y+height/2) 所以开始坐标小一点
654      *         公式还适用于其它规则图形
655      * 3.设置背景颜色:也是自己画的
656      */
657     public static void fish() {
658         int imageWidth = 800;
659         int imageHeight = 800;
660         BufferedImage img = new BufferedImage(imageWidth, imageHeight, 2);
661         Graphics2D pen = img.createGraphics();
662         //抗锯齿平滑
663         pen.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
664         pen.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
665         pen.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
666 
667         Color color = Color.YELLOW;
668         pen.setColor(color);
669         pen.fillRect(0,0,800,800);
670         Color white = Color.WHITE;
671         Color black = Color.black;
672 
673         pen.setColor(black);
674         pen.fillArc(0,0,800,800,-90,-180);
675         pen.setColor(white);
676         pen.fillArc(0,0,800,800,-90,180);
677         pen.setColor(black);
678         pen.fillArc(200,0,400,400,-90,180);
679         pen.setColor(white);
680         pen.fillArc(200,400,400,400,-90,-180);
681         pen.fillArc(350,150,100,100,0,360);
682         pen.setColor(black);
683         pen.fillArc(350,550,100,100,0,360);
684 
685         try {
686             ImageIO.write(img, "png", new File("fish.png"));
687             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" fish.png");
688         } catch (IOException e) {
689 
690         }
691     }
692     
693 
694     public static void main(String[] args) {
695 //        test();
696 //        System.out.println(getSystemFont());
697 //        testFont1();
698 //        testFont2();
699 //        testFont3();
700 //        testFigures();
701 //        fish();
702 //        testQr();
703 //        testQr2();//中文(多字节编码)
704 //        testQr3();
705 //        testQr4();
706 //        test11();
707 //        getQrCode(400,400,"https://www.baidu.com");
708 //        getInfo();
709         testcoding();
710     }
711 
712 }
复制代码

 

3.1EIO

复制代码
  1 package org.nio;
  2 
  3 /**
  4  * 简述:
  5  * Java NIO(New IO)是一个1可以替代标准java IO API的IO(从java1.4开始)
  6  * Java NIO提供了与标准IO不同的工作方式:通道和缓冲区
  7  * 标准的IO基于字节流和字符流进行IO操作,而NIO是基于通道和缓冲区进行操作,
  8  * 数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
  9  * Java NIO:非阻塞IO,
 10  * Java NIO引入了选择器的概念,选择器用于监听多个通道的时间,单线程可以监听多个数据通道
 11  * <p>
 12  * 经过试验验证
 13  * 1.如果IO次数是1,2次,选择IO,如果IO次数很多NIO效率稍稍高一点点
 14  * 2.他们本质都是IO操作工作方式不同
 15  * 3.NIO是官方在IO(字节)基础上封装了一下
 16  */
 17 
 18 
 19 import java.io.*;
 20 import java.nio.charset.StandardCharsets;
 21 import java.nio.file.*;
 22 import java.util.Arrays;
 23 import java.util.Iterator;
 24 import java.util.List;
 25 import java.util.concurrent.atomic.AtomicInteger;
 26 import java.util.stream.Stream;
 27 
 28 /**
 29  * 新的类 都看成是工具,专门处理文件,目录,流
 30  * import java.nio.file.DirectoryStream; 处理目录流
 31  * import java.nio.file.FileSystem; 处理文件流
 32  * import java.nio.file.FileSystems; 处理文件流
 33  * import java.nio.file.Files; 处理文件
 34  * import java.nio.file.Paths; 处理文件
 35  * import java.nio.file.attribute.FileAttribute; 处理文件
 36  * import java.nio.file.attribute.PosixFilePermission; 处理文件
 37  * import java.nio.file.attribute.PosixFilePermissions; 处理文件
 38  *
 39  */
 40 
 41 /**
 42  * 常用方法
 43  * Paths常用方法
 44  *
 45  * 1.获取Path实例化对象   Paths.get("d:/user")
 46  *
 47  * Files常用方法
 48  * 1.判断文件(包括目录)是否存在  Files.exists  文件最基础的操作--建议每一个操作前都添加
 49  *          判断是否是目录 Files.isDirectory()
 50  * 2.创建目录/文件  Files.createDirectory/Files.createFile
 51  *          多级目录 Files.createDirectories(目录存在不会报错) ; 不能建立多级文件
 52  * 3.删除目录/文件 : Files.delete()  只能删除空目录 没有返回值, Files.deleteIfExists(f);
 53  * );
 54  *          练习:递归删除非空目录 delDir
 55  * 4.查看目录下的文件, Files.newDirectoryStream  返回是一个目录流(这个方法很好)  DirectoryStream<Path>
 56  *          练习:
 57  *          递归遍历目录 seekDir
 58  *          统计某目录下有多少个java文件
 59  * 5.新建文件并在文件中写字符串 Files.writeString(Path,String)
 60  *          1.可以追加,选择编码 UTF_16 ,  StandardOpenOption.APPEND
 61  *
 62  * 6.创建文本文件读取流
 63  *          Files.newBufferedReader(Path,Charset)
 64  * 7.创建文本文件写入流
 65  *          Files.newBufferedWriter(Path,Charset)
 66  * 8.文件移动
 67  *          Files.move(Path,Path) 文件不存在会有异常
 68  * 9.复制(拷贝)文件
 69  *          Files.copy()
 70  *
 71  * 异常
 72  *java.nio.file.NoSuchFileException
 73  *java.nio.file.FileAlreadyExistsException
 74  */
 75 
 76 public class Test {
 77     public static void test() {
 78         try {
 79             if (!Files.exists(Paths.get("d:/user"))) {
 80                 Path path = Files.createDirectory(Paths.get("d:/user"));
 81                 System.out.println(path);
 82             }
 83             Path path = Files.createDirectories(Paths.get("d:/user/a/b/c/d"));
 84             System.out.println(path);
 85             if (!Files.exists(Paths.get("d:/user/ab/g.txt"))) {
 86                 path = Files.createFile(Paths.get("d:/user/ab/g.txt"));
 87                 System.out.println(path);
 88             }
 89         } catch (FileAlreadyExistsException e) {
 90             System.out.println("文件已经存在了,请你添加判断");
 91         } catch (IOException e) {
 92             System.out.println("IO异常,请检查");
 93             e.printStackTrace();
 94         }
 95     }
 96 
 97     public static void delDir(Path dir) {
 98         if (dir == null) {
 99             return;
100         }
101         if (Files.exists(dir)) {
102             if (Files.isDirectory(dir)) {
103                 try {
104                     //目录下的文件是流对象--会自动关闭,用完了(只能用一次)也会关闭。
105                     DirectoryStream<Path> paths = Files.newDirectoryStream(dir);
106                     //流处理--真正执行操作
107                     paths.forEach(path -> {
108                         try {
109                             if (Files.isDirectory(path)) {
110                                 delDir(path);
111                             } else {
112                                 Files.delete(path);
113                             }
114                         } catch (IOException e) {
115                             System.out.println("删除文件异常,请检查");
116                             throw new RuntimeException(e);
117                         }
118                     });
119                 } catch (IOException e) {
120                     throw new RuntimeException(e);
121                 }
122             }
123         }
124         try {
125             Files.delete(dir);
126         } catch (IOException e) {
127             throw new RuntimeException(e);
128         }
129     }
130 
131     //遍历目录,返回总的文件数,包括目录
132     public static int seekDir(Path dir) {
133         if (dir == null) {
134             return 0;
135         }
136         AtomicInteger count = new AtomicInteger(1);
137         if (Files.isDirectory(dir)) {
138             System.out.println("遍历目录:" + dir.getFileName());
139             try {
140                 DirectoryStream<Path> dirs = Files.newDirectoryStream(dir);
141                 if (dirs != null) {
142                     dirs.forEach(path -> {
143                         if (Files.isDirectory(path)) {
144                             count.addAndGet(seekDir(path));
145                         } else {
146                             System.out.println(path.getFileName());
147 //                            count++;
148                             count.addAndGet(1);
149                         }
150                     });
151                 }
152             } catch (IOException e) {
153 
154             }
155         }
156         return count.get();
157     }
158 
159     /**
160      * 小知识
161      * forEach里面不能用++,不能修改,基础数据类型,应该改变,并且调用方法 addAndGet增加
162      */
163 
164     public static int seekJavaFile(Path dir) {
165         if (dir == null) {
166             return 0;
167         }
168         int count = 0;
169         if (Files.exists(dir)) {
170             if (Files.isDirectory(dir)) {
171                 DirectoryStream<Path> paths;
172                 try {
173                     paths = Files.newDirectoryStream(dir);
174                     Iterator<Path> it = paths.iterator();
175                     while (it.hasNext()) {
176                         Path temp = it.next();
177                         if (Files.isDirectory(temp)) {
178                             count += seekJavaFile(temp);
179                         } else {
180                             if (temp.toString().endsWith(".java")) {
181                                 count++;
182                             }
183                         }
184                     }
185                 } catch (IOException e) {
186                     System.out.println("io异常,请检查");
187                     e.printStackTrace();
188                 }
189                 return count;
190             } else {
191                 if (dir.getFileName().toString().endsWith(".java")) {
192                     return 1;
193                 }
194             }
195         }
196         return 0;
197     }
198     /**
199      * 易错点
200      * Path也有endsWith()。但是和java的不同,它是看看文件路径结尾的文件
201      * 必须变为toString() Path里面也有endsWith()
202      */
203 
204 
205     /**
206      * 文件写入
207      */
208     public static void test2() {
209         try {
210 //            Files.writeString(Paths.get("my.txt"),"你好!\r\n学习javaIO");
211             byte[] bytes = "你好!\n学习javaIO".getBytes("UTF_16");
212             System.out.println(Arrays.toString(bytes) + new String(bytes, "UTF_16"));
213             bytes = "你好!\n学习javaIO".getBytes("utf-8");
214             System.out.println(Arrays.toString(bytes));
215             //不能同时用两种编码格式,文本只能用一种方式,所以只能识别英文
216             Files.writeString(Paths.get("my.txt"), new String("你好!\n学习javaIO".getBytes("UTF_16"), "UTF_16"), StandardCharsets.UTF_16);
217 //            Files.writeString(Paths.get("my.txt"),new String("你好!\n学习javaIO".getBytes("ISO_8859_1"),"ISO_8859_1"), StandardCharsets.ISO_8859_1,StandardOpenOption.APPEND);
218             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" my.txt");
219         } catch (IOException e) {
220             throw new RuntimeException(e);
221         }
222     }
223     /**
224      * 小知识
225      *1.ISO_8859_1 不支持中文 -- 不能用 部分欧洲人用
226      *2.写文件不能同时用两种编码格式,文本只能用一种方式打开,所以只能识别英文公共部分
227      */
228 
229     /**
230      * 文件添加行号
231      */
232     public static void addLineSign(Path path) {
233         if (Files.exists(path)) {
234             System.out.println("文件存在");
235             if (!Files.isDirectory(path)) {
236                 System.out.println("是一个文件");
237                 try {
238                     List<String> strings = Files.readAllLines(path);
239                     System.out.println("文件的总行数是" + strings.size());
240                     //向文件中写
241                     Iterator<String> it = strings.iterator();
242                     System.out.println(strings);
243                     int count = 0;
244 //            Files.delete(path);
245                     Files.writeString(path, "");
246                     while (it.hasNext()) {
247                         String temp = it.next();
248                         System.out.println(temp);
249                         Files.writeString(path, ++count + temp + "\r\n", StandardOpenOption.APPEND);
250                     }
251 //                    Files.writeString(path,++count,StandardOpenOption.APPEND);
252                 } catch (IOException e) {
253                     throw new RuntimeException(e);
254                 }
255             }
256         }
257     }
258     /**
259      * 易错点:
260      * 1.流每次都是覆盖,没有用一个写入流。
261      *      结果并不是没有写入(说明流关闭了),而是只有最后一次写入(前面的都被覆盖了)--故需要已追加方式,并且第一次需要把文件清空
262      * 2.读的时候一定保证文件存在
263      * 3.同样最后一行没法处理,
264      *            想处理了自己添加
265      *          -- 最后一行没有换行自己多写了
266      *            行尾添加换行会导致,自己需要在循环结束后补,并且会额外多一行。
267      * 4.读取的时候会把换行去掉,需要自己添加
268      */
269 
270     public static void addLineSign2(Path path){
271         //使用之前的方法
272         BufferedReader br = null;
273         try {
274             br = Files.newBufferedReader(path, StandardCharsets.UTF_8);
275         } catch (IOException e) {
276             throw new RuntimeException(e);
277         }
278         String st = null;
279         try {
280             Stream<String> lines = br.lines();
281 
282             BufferedWriter write = Files.newBufferedWriter(Paths.get("eidLine.txt"), StandardCharsets.UTF_8);
283             AtomicInteger count = new AtomicInteger();
284             lines.forEach(line -> {
285                 try {
286                     write.write(count.incrementAndGet() + line +"\r\n");
287                 } catch (IOException e) {
288                     throw new RuntimeException(e);
289                 }
290             });
291         }
292         catch(IOException e) {
293 
294         }
295     }
296     /**
297      * 其它
298      * foreach写入时候只写了一点
299      */
300     /**
301      * String类的format方法
302      */
303     public static void testStringFormat(){
304         byte[] bytes = String.format("姓名:%s、年龄:%d","张三",11).getBytes();
305         System.out.println(new String(bytes));
306         try {
307             Files.writeString(Paths.get("aaaa.txt"),String.format("年龄:%02d、姓名:%s",11,"张三"));
308             Runtime.getRuntime().exec("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" aaaa.txt");
309 
310         }
311        catch (IOException e) {
312 
313        }
314     }
315 
316     /**
317      * 文件移动
318      *      剪贴粘贴
319      *      特殊的移动,改名
320      * 文件拷贝
321      *      copy
322      *      transferTo jdk 9
323      *
324      * 1.异常:Files.copy 文件不存在,文件已经有了都会出现问题
325      * 2.transferTo 底层是一个缓冲
326      */
327     public static void test3(){
328         try {
329 //            Files.move(Paths.get("a.txt"),Paths.get("b.txt"));
330 //            Files.copy(Paths.get("a.txt"),Paths.get("b.txt"));
331             FileInputStream fis= new FileInputStream("a.txt");
332             fis.transferTo(new FileOutputStream("bb.txt"));
333         } catch (IOException e) {
334             throw new RuntimeException(e);
335         }
336     }
337 
338     public static void main(String[] args) {
339 //        test();
340 //        delDir(Paths.get("d:/user/a"));
341 //        System.out.println("工作目录一共"+seekDir(Paths.get(System.getProperty("user.dir")))+"个文件(包含目录)");
342 //        System.out.println("工作目录一共"+seekDir(Paths.get(""))+"个文件(包含目录)");
343 //        System.out.println("工作目录一共"+seekDir(Paths.get("."))+"个文件(包含目录)");
344 //        System.out.println("工作目录一共"+seekJavaFile(Paths.get("."))+"个java文件");
345 //        System.out.println(Paths.get("d:/user/a/b").endsWith("a/b"));//true
346 //        System.out.println(Paths.get("d:/user/a/b").endsWith("a"));//false
347 //        test2();
348 //        addLineSign(Paths.get("eid.java"));
349 //        addLineSign2(Paths.get("eid.java"));
350 //        testStringFormat();
351         test3();
352     }
353     /**
354      * 小知识
355      * 表示当前目录(工作路径)的3种方式
356      *  "AAA"  和"aaa" 和 "./aaa""./AAA" 和"AAA/"  和"aaa/"和"AAA/."  和"aaa/."一样
357      * 1.System.getProperty("user.dir")
358      * 2.相对路径  ""  "."
359      */
360 }
复制代码

 

posted @   liu/564  阅读(72)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示