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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)