文档章节

【java数据科学】1.提取数据以及清洗数据

Areya
 Areya
发布于 02/12 15:34
字数 2154
阅读 15
收藏 0

简介

该系列主要总结了使用java处理数据过程中使用到的工具以及一些可以起到启发性的代码。通过本章节你可以学习到:

  • 如何递归遍历文件目录
  • 如何访问各种各样的数据源

1、遍历文件

1.1、使用基本方法列出目录下的所有文件

import java.io.File;
import java.util.HashSet;
import java.util.Set;

public class ListFilesWithSimple {
    public static void main(String[] args) {
        // 1.使用java从分层目录中提取所有文件名
        Set<File> files = ListFilesWithSimple.listFiles(new File("D:/hadoop"));
        for (File file : files) {
            System.out.println(file.getPath());
        }
    }

    // 1. 从分层目录中提取所有文件名(注意不包含文件夹)
    public static Set<File> listFiles(File rootDir){
        Set<File> fileSet = new HashSet<File>();
        // when file is null or file is not a directory.
        if(rootDir == null || rootDir.listFiles() == null){
            return fileSet;
        }
        for (File file : rootDir.listFiles()) {
            if(file.isFile()){
                fileSet.add(file);
            }else{
                fileSet.addAll(listFiles(file));
            }
        }
        return fileSet;
    }
}

1.2、使用Apache Commons IO 从多层目录中提取所有文件

引入依赖

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;

import java.io.File;
import java.util.List;

public class ListFilesWithCommonIo {
    public static void main(String[] args) {
        List<File> files = ListFilesWithCommonIo.listFiles(new File("D:/hadoop"));
        for (File file : files) {
            System.out.println(file.getAbsolutePath());
        }

    }

    public static List<File> listFiles(File rootDir){
        return (List<File>)FileUtils.listFiles(rootDir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
        // 若需要返回目录
        //return (List<File>)FileUtils.listFilesAndDirs(rootDir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
    }
}

2、读取内容

2.1、使用java8按行读取

package read;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class Java8Read {
    public static void main(String[] args) {
        // 文件
        String file = "锦瑟.poetry";
        try {
            Stream<String> lines = Files.lines(Paths.get(file));
            // 显示每一行数据
            lines.forEach(line -> System.out.println(line));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2、使用Commons IO一次性读取

package read;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;

public class CommonIORead {
    public static void main(String[] args) {
        String file = "天净沙-秋思.poetry";
        try {
            String content = FileUtils.readFileToString(new File(file), "UTF-8");
            System.out.println(content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.3、使用Apache Tika提取PDF文本

导入依赖

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-parsers</artifactId>
    <version>1.20</version>
</dependency>
package read;

import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;

import java.io.FileInputStream;
import java.io.InputStream;

public class TiKaRead {
    public static void main(String[] args) {
        String content = readPDF("他不懂.pdf");
        System.out.println(content);
    }

    public static String readPDF(String fileName){
        InputStream inputStream = null;
        String content = "";
        try {
            inputStream = new FileInputStream(fileName);
            // 创建一个自动解析器
            AutoDetectParser parser = new AutoDetectParser();
            // 使用-1表示不对文件内容的大小进行限制
            BodyContentHandler handler = new BodyContentHandler(-1);
            Metadata metaData = new Metadata();
            parser.parse(inputStream, handler, metaData, new ParseContext());
            System.out.println(metaData);
            // 调用Handler对象的toString获取正文内容
            content = handler.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(inputStream != null){
                try{
                    inputStream.close();
                }catch (Exception e){
                    System.out.println("Error Closing input stream.");
                }
            }
        }
        return content;
    }
}

3、清洗文件

3.1、使用正则表达式清洗ASCII文本

package filter;

import com.sun.media.jfxmedia.track.Track;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

public class FilterASCII {
    public static void main(String[] args) {
        try {
            System.out.println(cleanText("this s a 赵义    text."));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String cleanText(String text){
        // 1.去除所有非ASCII字符
        text = text.replaceAll("[^\\p{ASCII}]","");
        // 2.去除多余的空格
        text = text.replaceAll("\\s+"," ");
        // 3.清除ASCII控制字符
        text = text.replaceAll("[\\p{Cntrl}]","");
        // 4.清除非打印字符
        text = text.replaceAll("[^\\p{Print}]","");
        return text;
    }
}

4、解析文件

4.1、使用Univocity解析CSV文件

引入依赖

<dependency>
    <groupId>com.univocity</groupId>
    <artifactId>univocity-parsers</artifactId>
    <version>2.8.1</version>
</dependency>

有很多采用Java编写的csv文件解析器。不过,Univocity是相对比较快的一种。

package parser;

import com.univocity.parsers.common.processor.RowListProcessor;
import com.univocity.parsers.csv.CsvParser;
import com.univocity.parsers.csv.CsvParserSettings;

import java.io.File;
import java.util.Arrays;
import java.util.List;


public class UnivocityTest {
    public static void main(String[] args) throws Exception{
        String fileName = "模块表.csv";
        parseCSV(fileName);
    }

    public static void parseCSV(String fileName) throws Exception {
        // 创建一个配置对象,并配置
        CsvParserSettings csvParserSettings = new CsvParserSettings();
        // 自动检测输入中的分隔符序列
        csvParserSettings.setLineSeparatorDetectionEnabled(true);
        // 指定把每个解析的行存储在列表中,写入配置:使用rowListProcessor配置解析器,用来对每个解析行的值进行处理
        RowListProcessor processor = new RowListProcessor();
        csvParserSettings.setProcessor(processor);
        // 若CSV文件包含标题头,则可以把第一行看做文件中每个列的标题;否则无需设置。
        //csvParserSettings.setHeaderExtractionEnabled(true);
        // 使用给定的配置创建一个parser实例
        CsvParser csvParser = new CsvParser(csvParserSettings);
        csvParser.parse(new File(fileName));

        // 默认将第一行看做头
        String[] headers = processor.getHeaders();
        System.out.println(Arrays.asList(headers));

        List<String[]> rows = processor.getRows();
        for (String[] row : rows) {
            System.out.println(Arrays.asList(row));
        }


    }
}

4.2、使用Univocity解析TSV文件

TSV和CSV几乎是同一类文件,只不过是TAB分隔不同列。

package parser;

import com.univocity.parsers.tsv.TsvParser;
import com.univocity.parsers.tsv.TsvParserSettings;

import java.io.File;
import java.util.Arrays;
import java.util.List;


public class UnivocityTest2 {
    public static void main(String[] args) {
        String fileName = "模块表.tsv";
        parseTSV(fileName);
    }

    public static void parseTSV(String fileName){
        // 创建一个配置对象,并配置
        TsvParserSettings settings = new TsvParserSettings();
        // 设置行分隔符
        settings.getFormat().setLineSeparator("\n");
        // 使用配置创建一个parser
        TsvParser parser = new TsvParser(settings);
        // 将文件内容一次性解析出来
        List<String[]> rows = parser.parseAll(new File(fileName));
        for (String[] row : rows) {
            System.out.println(Arrays.asList(row));
        }

    }
}

4.3、使用JDOM解析XML文件

导入依赖

<!-- https://mvnrepository.com/artifact/org.jdom/jdom2 -->
<dependency>
    <groupId>org.jdom</groupId>
    <artifactId>jdom2</artifactId>
    <version>2.0.6</version>
</dependency>
package parser;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class JDomTester {
    public static void main(String[] args) {
        parserXML("类型.xml");
    }

    public static void parserXML(String fileName){
        File file = new File(fileName);
        SAXBuilder builder = new SAXBuilder();
        try {
            // 创建一个Document对象,代表访问的XML文件
            Document doc = builder.build(file);
            // 获取根元素
            Element rootEle = doc.getRootElement();
            // 获取根元素下的所有数据
            List<Element> records = rootEle.getChildren("RECORD");
            // 遍历节点
            for (Element record : records) {
                System.out.println("====== record ======");
                System.out.println("id:" + record.getChildText("type_id"));
                System.out.println("name:" + record.getChildText("type_name"));
                System.out.println("state:" + record.getChildText("state"));
                System.out.println("create time:" + record.getChildText("create_time"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.4、使用JSON.simple与JSON文件交互(写入和读取)

引入依赖

<!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
<dependency>
    <groupId>com.googlecode.json-simple</groupId>
    <artifactId>json-simple</artifactId>
    <version>1.1.1</version>
</dependency>
package parser;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

import java.io.FileReader;
import java.io.FileWriter;

public class JsonTester {
    public static void main(String[] args) throws Exception{
        String fileName = "书籍.json";
        writeJSONFile(fileName);
        readJSONFile(fileName);
    }

    public static void writeJSONFile(String fileName){
        // 创建JSON对象
        JSONObject obj = new JSONObject();
        obj.put("name","来自新世界");
        obj.put("author","贵志佑介");
        obj.put("introduce", "一部畅想未来的架空世界观的小说,不同于大多数科幻作品的风格,作者对未来展现的不是高科技时代,而是看起来甚至是比现在还要倒退一千年的时代...");
        // 添加3个书籍评论
        JSONArray comments = new JSONArray();
        comments.add("这是一本可以打满分的书。");
        comments.add("这是一本可以打90分的书。");
        comments.add("这是一本一般般的书。");
        obj.put("comments", comments);

        // 写入json文件
        FileWriter writer = null;
        try {
            writer = new FileWriter(fileName);
            System.out.println(obj.toJSONString());
            writer.write(obj.toJSONString());
            writer.flush();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void readJSONFile(String fileName) throws Exception {
        // 创建一个JSON解析器
        JSONParser parser = new JSONParser();
        // 解析
        JSONObject object = (JSONObject)parser.parse(new FileReader(fileName));

        System.out.println("====== book info =======");
        System.out.println("name:" + object.get("name"));
        System.out.println("author:" + object.get("author"));
        System.out.println("introduce:" + object.get("introduce"));
        System.out.println("comments:" + object.get("comments"));
    }
}

还有一个工具包叫做fastjson,同样是google出品。

4.5、使用JSoup从一个URL中提取Web数据

jsoup是一个不错的解析工具,其解析速度非常之快。究其原因,主要是不需要对网页进行动态解析,也不支持对网页就行任何动态操作,而是直接解析第一次访问获得的内容。因此,在使用jsoup的时候如果有其他需求,例如想要调用按钮点击事件、触发远程调用等,应该考虑使用其他的工具,例如python一个很出名的爬虫框架selenium,该工具在java也有一个对应的工具包。

引入依赖

<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.11.3</version>
</dependency>
package parser;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;

public class JSoupTester {
    public static void main(String[] args) {
        extractDataByJSoup("https://www.baidu.com/");
    }

    public static void extractDataByJSoup(String url){
        try {
            Document doc = Jsoup.connect(url).timeout(10 * 1000).ignoreHttpErrors(true).get();
            if(doc == null){
                System.out.println("This url is null.");
                return;
            }
            // 提取网址标题
            System.out.println("====== The Web Info ======");
            System.out.println("title:" + doc.title());
            // 提取正文内容
            System.out.println("body content:" + doc.body().text());
            // 获取所有超链接:css选择器的写法
            System.out.println("all href:" + doc.select("a[href]"));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.6、使用Selenium WebDriver从网站中提取Web数据

使用这些工具的时候还需要在所在的服务器上安装对应的浏览器包,这里就不一一介绍了。

5、从MySQL数据库读取表格数据

读取mysql数据的方式相信只要是一个开发者,都掌握了各种五花八门的方式了,甚至编写了自己的访问框架。这里我们就学习一下比较原始的访问方式,不去深究一些主流框架的使用。

引入依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.13</version>
</dependency>
package visit;

import com.mysql.cj.jdbc.MysqlDataSource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class MySQLTester {
    public static void main(String[] args) throws Exception {
        visitMysqlData();
    }

    public static void visitMysqlData() throws Exception {
        MysqlDataSource dataSource = new MysqlDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("your_database_password");
        // 这里输入您的数据库地址,例如本机localhost
        dataSource.setServerName("10.21.1.242");

        // 建立连接
        Connection connection = dataSource.getConnection();
        Statement statement = connection.createStatement();

        // 获取查询数据:sunrun_sdfs是库名,sdfs_user是表明
        ResultSet resultSet = statement.executeQuery("select * from sunrun_sdfs.sdfs_user limit 5");

        while (resultSet.next()){
            System.out.println("====== user info ======");
            System.out.println("id: " + resultSet.getString("user_id"));
            System.out.println("name: " + resultSet.getString("user_name"));
            System.out.println("login name: " + resultSet.getString("login_name"));
        }
        resultSet.close();
        statement.close();
        connection.close();
    }
}

© 著作权归作者所有

Areya
粉丝 27
博文 91
码字总数 163202
作品 0
广州
私信 提问
做数据分析必须了解的获取数据与清洗数据技巧

点击关注 异步图书,置顶公众号 每天与你分享 IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书 ——异步小编 每个数据科学家都需要处理存储在磁盘中的数据,这些数据涉及的格式...

异步社区
2018/05/21
0
0
Java程序员必读书单,家族又添新成员

点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书。 ——异步小编 有些革命出其不意地吸引了全世界的眼球。Twitter、Linux操作系统和...

异步社区
2018/05/09
0
0
福利丨拿下这些大数据好书,在11月做更好的自己!

据小编的不完全观察,近期发布的大数据文章都好评如潮,送出的大数据书籍也都受到了大家的热捧和喜爱。因此,为了满足大家日益增长的学习需求与激情,小编在此快马加鞭携手@图灵教育,带来一...

DBAplus社群
2017/10/31
0
0
Kafka连接器深度解读之JDBC源连接器

在现实业务中,Kafka经常会遇到的一个集成场景就是,从数据库获取数据,因为关系数据库是一个非常丰富的事件源。数据库中的现有数据以及对该数据的任何更改都可以流式传输到Kafka主题中,在这...

李玉珏
03/12
0
0
使用shell分页读取600万+的MySQL数据脚本

shell-mysql (1)脚本背景: 由于要在Linux上,远程读取mysql的表的数据,然后做一定清洗后,把数据上传至Hadoop集群中,使用Java写吧,感觉太麻烦了,得在Win上开发好,还得打成jar包, 上传...

九劫散仙
2015/07/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux scp命令

Linux scp命令 Linux 命令大全 Linux scp命令用于Linux之间复制文件和目录。 scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令。 语法 scp [-1246BCpqrv] ...

linjin200
21分钟前
3
0
Echoin获得ZB Captial战略投资

Echoin获得ZB Captial战略投资

怎当她临去时秋波那一转
22分钟前
2
0
Jenkins 持续集成综合实战

Jenkins 持续集成综合实战 发表于 2017-01-06 文章目录 1 安装 Jenkins 1.1 安装 JDK/Maven 1.2 安装 Jenkins 1.2.1 离线安装 1.2.2 在线安装 1.2.3 基于 Tomcat 安装 1.2.4 免安装方式 1.3 ...

linzhuangrong
23分钟前
2
0
自动编码(AE)器的简单实现

一.目录 自动编码(AE)器的简单实现 一.目录 二.自动编码器的发展简述 2.1 自动编码器(Auto-Encoders,AE) 2.2 降噪自编码(Denoising Auto-Encoders, DAE)(2008) 2.3 堆叠降燥自动编码器 (Sta...

zhaowei121
27分钟前
2
0
十分良心!全网最详细的Java 自动内存管理机制及性能优化教程

先来个思维导图预览一下本文结构。 一图带你看完本文 一、运行时数据区域 首先来看看Java虚拟机所管理的内存包括哪些区域,就像我们要了解一个房子,我们得先知道这个房子大体构造。根据《J...

戎码益深
27分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部