北京车和家java开发工程师面试题总结,java开发工程师面试题


题目描述:

笔试题: CSV 文件处理

给定一个 CSV 文件,其内容的展现规则如下:

 

- 每一行数据包含多个字段,字段间以 [,] 分割。

- 如果字段值不含有 [,] 和 ["] ,直接解析输出。

- 如果字段值内部含有逗号 [,],在在字段值两边加上双引号 ["] 将字段值括起来。

- 如果字段值内部含有双引号 ["],则字段值两边加上双引号 ["] 括起来,同时,将字段值内的一个双引号 ["] 替换为两个双引号 [""],例如: [下棋,"飞"] 在 CSV 文件中被表现为 ["下棋,""飞"""]。

处理要求:

读入文件 cvs.txt,根据上述 csv 文件的规则进行解析,重新格式化字段生成输出文件 output.txt

第一列转为整形(int)

第二列为字符串型

第三列为字符串型

第四列转为浮点数(float)

第五列转为日期类型(DateTime)

 

输出文件的字段以制表符 [TAB] 来分割字段,

字符串字段输出时用单引号[']括起来

日期字段显示成 YYYY/MM/DD 的格式

 

说明:

1、可以假设字段值只包含单行数据,即字段值本身不含有 [回车换行]

2、不能对文件 csv.txt 作任何修改

 

编程要求:

 

使用任何你熟悉的编程语言编写,时间为 1.5 小时。

题目意思:

这个题目意思描述的不是很清楚,就是给你一个格式化后的csv文件,重新还原到刚开始的文件

还有就是,字段值中同时有 [,] 和 ["] 只会在最外层加一次["]

思路:

1. 主要难点在于第二列和第三列如何区分开,因为第二列和第三列都是字符串

2. 区分的思路为,遍历所有[,],如果[,]左边["]的个数和右边["]的个数都为偶数,则这个[,]为分隔第二个字符串和
第三个字符串的分界点

3. 找到分界点后,格式化输出即可

代码:

package com.st.solution.main;

import com.st.solution.util.DateTimeUtil;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: lilimin
 * @Date: 2019/6/28 20:09
 */
public class Solution {

    public static void main(String[] args) {

        String readFileName = "src/main/resources/csv.txt";
        String writeFileName = "src/main/resources/output.txt";
        readAndWriteFile(readFileName, writeFileName);
    }

    /**
     * 读入文件,格式化输出
     * @param readFileName
     * @param writeFileName
     */
    public static void readAndWriteFile(String readFileName, String writeFileName) {
        BufferedReader reader = null;
        BufferedWriter writer = null;
        try {
            reader = new BufferedReader(new FileReader(new File(readFileName)));
            writer = new BufferedWriter(new FileWriter(new File(writeFileName)));
            String line = null;
            while ((line = reader.readLine()) != null) {
                String formatText = formatText(line);
                writer.write(formatText);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 格式化每一行数据的输出
     * @param text
     * @return
     */
    public static String formatText(String text) {
        // 如果字段值不含有 [,] 和 ["] ,直接解析输出。
        if (!text.contains(",") && !text.contains("\"")) {
            return text;
        }

        String[] splitTextArray = text.split(",");
        int arrayLength = splitTextArray.length;

        List<String> tempList = new ArrayList<String>();
        tempList.add(splitTextArray[0]);

        // 如果split后的数组长度为4,说明字符中间没有,
        if (arrayLength == 4) {
            tempList.add(formatStrText(splitTextArray[1]));
            tempList.add(formatStrText(splitTextArray[2]));
        } else {
            // 第2列 或者 第3列 字符中间有,

            // 获取第二列和第三列合起来的字符串
            StringBuilder middleText = new StringBuilder();
            for (int i = 1; i <arrayLength - 3 ; i++) {
                middleText.append(splitTextArray[i]).append(",");
            }
            middleText.append(splitTextArray[arrayLength- 3]);

            // 获取第二列和第三列格式化后的字符串
            List<String> middleTextList = formatMiddleText(middleText.toString());
            tempList.addAll(middleTextList);
        }

        tempList.add(splitTextArray[arrayLength - 2]);
        tempList.add(DateTimeUtil.transferDateformat(splitTextArray[arrayLength - 1]));


        return String.join("    ", tempList) + "\n";
    }

    /**
     * 格式化string类型的字符串
     * @param text
     * @return
     */
    public static String formatStrText(String text) {
        if (text.startsWith("\"") && text.endsWith("\"")) {
            text = text.substring(1, text.length() - 1);
        }
        text = text.replaceAll("\"\"", "\"");
        return "'" + text + "'";
    }

    /**
     * 找出第二列和第三列的分界点[,],并且格式化第二列和第三列
     * 原则如下,遍历所有[,],如果某个[,] 左边的["]个数和右边的["]个数都为偶数
     * 则一定是第二三列的分界点
     * @param text
     * @return
     */
    public static List<String> formatMiddleText(String text) {
        List<String> list = new ArrayList<String>();
        String tempText = text;
        int index = -1;
        while ((index = tempText.indexOf(",", index + 1)) != -1) {
            int leftSum = 0;
            int rightSum = 0;
            for (int i = 0; i < index; i++) {
                if (text.charAt(i) == '"') {
                    leftSum++;
                }
            }
            for (int i = index + 1; i < text.length(); i++) {
                if (text.charAt(i) == '"') {
                    rightSum++;
                }
            }
            if ((leftSum & 1) == 0 && (rightSum & 1) == 0) {
                break;
            }
        }
        list.add(formatStrText(text.substring(0, index)));
        list.add(formatStrText(text.substring(index + 1)));
        return list;
    }

}
/**
 * @Author: lilimin
 * @Date: 2019/6/28 20:09
 */
public class DateTimeUtil {


    /**
     * 将 yyyy-MM-dd 格式的日期字符串转为 yyyy/MM/dd 格式的日期字符串
     * @param timestr
     * @return
     */
    public static String transferDateformat(String timestr) {
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("YYYY/MM/DD");
        Date parse = null;
        try {
            parse = sdf1.parse(timestr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sdf2.format(parse);
    }
}

我代码最后的output.txt的内容为

1    'Jane'    '下"棋,"飞"'    56.2    1976/08/236
2    'Kate'    '购物'    49.6    1980/01/25
3    'Jerry'    '羽毛球,爬山'    55.6    1980/05/147

作为一个完整的工程,单测必不可少


/**
 * @Author: lilimin
 * @Date: 2019/6/29 16:14
 */
public class SolutionTest {

    @Test
    public void readAndWriteFile() {
        String readFileName = "src/main/resources/test1csv.txt";
        String writeFileName = "src/main/resources/test1output.txt";

        Solution.readAndWriteFile(readFileName, writeFileName);

        readFileName = "src/main/resources/test2csv.txt";
        writeFileName = "src/main/resources/test2output.txt";

        Solution.readAndWriteFile(readFileName, writeFileName);
    }

    @Test
    public void formatStrText() {
        String text = Solution.formatStrText("\"\"\"text\"\"\"");
        assertEquals("'\"text\"'", text);
    }

    @Test
    public void formatMiddleText() {
        List<String> textList = Solution.formatMiddleText("str1,str2");
        assertEquals("'str1'", textList.get(0));
        assertEquals("'str2'", textList.get(1));

        textList = Solution.formatMiddleText("\"str1\",\"str2\"");
        assertEquals("'str1'", textList.get(0));
        assertEquals("'str2'", textList.get(1));

        textList = Solution.formatMiddleText("\"\"\"str1\",\"str2\"");
        assertEquals("'\"str1'", textList.get(0));
        assertEquals("'str2'", textList.get(1));
    }
}

单测的输入和输出如下

test1.csv

2,",Kate",购物,49.6,1979-12-56
3,Jerry,"羽毛球,爬山",55.6,1980-5-26

test1output.txt

2    ',Kate'    '购物'    49.6    1980/01/25
3    'Jerry'    '羽毛球,爬山'    55.6    1980/05/147

test2.csv

1,Jane,"下""棋,""飞""",56.2,1976-8-23
2,"Kate,Kate","购物,购物",49.6,1979-12-56
3,Jerry,"羽毛球,爬山",55.6,1980-5-26

test2output.txt

1    'Jane'    '下"棋,"飞"'    56.2    1976/08/236
2    'Kate,Kate'    '购物,购物'    49.6    1980/01/25
3    'Jerry'    '羽毛球,爬山'    55.6    1980/05/147

推荐

文章最后发布于: 2019-07-06 17:23:38

相关内容

    暂无相关文章