java中文件读写与图像处理
文件处理
如何读取文件
Java对于文件的读取操作,都是InputStream子类来完成的。创建一个名为“test.text”的文本文件,并输入以下内容:
这是一个测试文件第2行第3行这行故意留空
以下是几个示例,展示了如何使用BufferedReader和FileInputStream读取文件:
一行一行读取
public class FileReadDemo { public static void main(String[] args) throws IOException { //创建一个文件对象,文件内容为test.text File file = new File("./test.text"); //利用BufferedReader来读取文件 try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) { String line = null; while (null != (line = bufferedReader.readLine())) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } }
每次只读取一行,当文件读完之后会返回一个null,表示文件已经读完,将打开流的操作放在try里面,会自动为我们关闭流。
Java8及其以后的JDK还给我们提供了一种更为简便的方法,叫lambda表达式,关于lambda表达式,会专门写一篇文档,感兴趣的可以先了解一下
public class FileReadDemo { public static void main(String[] args) throws IOException { File file = new File("./test.text"); Files.lines(file.toPath()).forEach(System.out::println); } }
指定大小读取文件
很多情况下我们需要读取文件,但是每次只需要读几个字符,这种情况下我们就可以指定一次读取字符的个数
public class FileReadDemo { public static void main(String[] args) throws IOException { File file = new File("./test.text"); try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) { //每次读取10个字符 char[] chars = new char[10]; //内容读完之后就会返回一个-1的值 while (-1 != bufferedReader.read(chars)){ System.out.println(new String(chars)); } } catch (IOException e) { e.printStackTrace(); } } }
一次性读取10个字符,char[] chars = new char[10];可以改变这行代码中的10来调整一次性读取的字符数量
一次性读取整个文件
public class FileReadDemo { public static void main(String[] args) throws IOException { File file = new File("./test.text"); //file.length返回的文章的字节数 Long length = file.length(); try (FileInputStream f = new FileInputStream(file)) { byte[] bytes = new byte[length.intValue()]; while (-1 != f.read(bytes)) { System.out.println(new String(bytes)); } } catch (IOException e) { e.printStackTrace(); } } }
file.length()表示文件的字节数,我们将一次性读取的长度定位文件的长度,即可一次性读取出文件的所有内容,这种读取方式适合任何文件类型
如何写文件
写文件一般是由OutputStream子类来实现的。
追加写入
public class FileReadDemo { public static void main(String[] args) throws IOException { File file = new File("./test.text"); //new FileOutputStream(file,true),true表示以追加的方式写入文件,意味着会把hello world写到文档内容的最后 try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file,true))) { bufferedOutputStream.write("hello world".getBytes()); } catch (IOException e) { e.printStackTrace(); } } }
清空文件内容重新写入
public class FileReadDemo { public static void main(String[] args) throws IOException { File file = new File("./test.text"); //new FileOutputStream(file),没有指定写的模式将会清空文档内容重新加入 //new FileOutputStream(file,false),false表示清空文档的内容,只写入hello world try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file))) { bufferedOutputStream.write("hello world".getBytes()); } catch (IOException e) { e.printStackTrace(); } }}
清空写入和追加写入取决于FileOutputStream流的模式,通过指定append参数可以控制是追加,还是清空写入
至此,文件的读取和写入,已经介绍完毕了。
图片处理
日常工作中,经常会遇到要批量的给图片加滤镜,加水印,按需求缩放图片等操作,如果不懂编程,可能就需要你用ps一张一张的打开图片,修改图片再保存,大量的重复工作将占用你很多宝贵的时间。如果需要处理的图片量大,即便是加班,也不一定能及时完成工作,且及其容易操作失误导致出错。
好在之前的任务中,我们已经掌握了批量搜索和处理文件的能力,也知道了如何用Java来读写文件,现在我们只需要掌握任意一种图片处理库,就能很方便的用脚本来帮助我们完成今天的任务。
图像缩放
工作中可能经常需要对图片做一些调整大小的操作,这里我们用Java实现一个方法,将图片按照比例缩放至原来的80%,你可以稍微改动一下这个方法,让图片可以任意比例缩放。准备一张图片,并命名为test.png,并将图片放入到项目的根目录中,根目录即为项目文件夹的路径
public class ImageDemo { public static void main(String[] args) throws IOException { //创建一个文件对象 File file = new File("test.png"); try {- //BufferedImage是Image与图像数据的访问的缓冲器 BufferedImage image = ImageIO.read(file); int width = image.getWidth(); int height = image.getHeight(); //创建此图像的缩放版本。 返回一个新的Image对象 Image scaledInstance = image.getScaledInstance(Double.valueOf(width * 0.8).intValue(), Double.valueOf(height * 0.8).intValue(), Image.SCALE_DEFAULT); //确定图像的宽度。 如果宽度未知,则此方法返回-1并稍后通知指定的ImageObserver对象 int swidth = scaledInstance.getWidth(null); int sheight = scaledInstance.getHeight(null); BufferedImage newImage = new BufferedImage(swidth, sheight, BufferedImage.TYPE_INT_ARGB); //Graphics对象封装了 Java 支持的基本渲染操作所需的状态信息,可以理解为是一支画笔 Graphics g = newImage.getGraphics(); //从坐标0,0处画一个图像 g.drawImage(scaledInstance, 0, 0, null); //处理此图形上下文并释放它正在使用的任何系统资源。 调用dispose后无法使用Graphics对象。 g.dispose(); //将新的图片信息写入scaled.png ImageIO.write(newImage, "png", new File("scaled.png")); } catch (IOException ioException) { ioException.printStackTrace(); } } }
图像滤镜
图像滤镜是图像处理中经常需要用到的操作,比如美颜中的磨皮操作就能让人肤白貌美,这个磨皮就用到了模糊滤镜;把彩色照片转化成黑白照片或者老旧照片就需要用到颜色滤镜,如果你对位图的的数据编码方式非常熟悉,你可以自己利用PIL创造特定的滤镜。(比较有难度,通常大部分开发者都不会自己去创建滤镜)
Java有很多开源工具给我们提供了对应的功能,因此我们可以直接拿来使用,这里介绍一个Java的图片滤镜处理工具Java Image Filters,官网如下
http://www.jhlabs.com/ip/filters/index.html
这里我们选择InvertFilter反转颜色滤镜,在官网将Filters.jar下载下来并导入到工程中
import com.jhlabs.image.InvertFilter;import javax.imageio.ImageIO;import java.awt.*;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;public class ImageDemo { public static void main(String[] args) throws IOException { File file = new File("test.png"); BufferedImage sourceImage = ImageIO.read(file); Image scaledInstance = sourceImage.getScaledInstance(sourceImage.getWidth(), sourceImage.getHeight(), Image.SCALE_DEFAULT); BufferedImage newImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics g = newImage.getGraphics(); g.drawImage(scaledInstance, 0, 0, null); g.dispose(); File desfile = new File("testDes.png"); //反转颜色滤镜 InvertFilter invertFilter = new InvertFilter(); invertFilter.filter(sourceImage, newImage); ImageIO.write(newImage, "png", desfile); } }
调用这个方法后,test.png这张图片中所有的颜色都会反转,只需要几行代码,就可以完成这个操作
绘图方法
Java也能完成图片的创建,
这里我们创建一个灰色的图片,上面写一个黄色的hello world
import com.github.javafaker.Faker;import org.apache.poi.xssf.usermodel.XSSFRow;import org.apache.poi.xssf.usermodel.XSSFSheet;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.List;import java.util.Locale;import java.util.stream.Collectors;import java.util.stream.Stream;public class ImageDemo { public static void main(String[] args) throws IOException { //画一个400*400的灰色图片 BufferedImage bufferedImage = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB); Graphics g = bufferedImage.getGraphics(); g.setColor(Color.GRAY); g.fillRect(0, 0, 400, 400); //在上面写上黄色的hello wolrd g.setColor(Color.YELLOW); //设置字体,加粗,大小 Font font = new Font("SimHei", Font.BOLD, 50); g.setFont(font); g.drawString("hello world", 100, 200); g.dispose(); ImageIO.write(bufferedImage, "png", new File("gray.png")); } }
另外一个常用的功能就是给图片加水印,用代码也能很方便的实现,这里就将一个黄色的hello world字样放到了图片上
public class ImageDemo { public static void main(String[] args) throws IOException { BufferedImage bufferedImage = ImageIO.read(new File("test.png")); Graphics g = bufferedImage.getGraphics(); //在上面写上黄色的hello world g.setColor(Color.YELLOW); Font font = new Font("SimHei", Font.BOLD, 50); g.setFont(font); g.drawString("hello world", 100, 200); g.dispose(); ImageIO.write(bufferedImage, "png", new File("watermark.png")); } }