程序员老鬼

某大厂员工吐槽:某程序员:高杠杆生活太可怕了!同事被裁赔偿了30万,大家都以为他会开心,但他深圳房贷每月就有3万,30万也撑不了多久

被裁赔30万,结果一听房贷,笑容当场没了。

深圳这类高杠杆日子,平时看着挺体面,真出点事,立马原形毕露。一个月房贷3万,30万赔偿金听着不少,真摊开算,也就是十个月呼吸权。还没算吃饭、养家、通勤、社保这些零零碎碎。你以为是缓冲垫,实际上更像延迟爆炸。

Image

我看最扎心的点就在这儿:很多程序员不是工资高,是欠得多。上班那会儿觉得自己扛得住,裁员通知一来,才发现不是人在养房,是房在拴人。

大厂工牌一摘,最先扑上来的不是诗和远方,是下个月的还款日。你说30万少不少?单看数字不小,搁这种日子里,也就够人晚上少失眠几个月。

面试题:第十行

文件题最怕两种写法。一种是上来就把整个文件一次性读进内存,明明只要第 10 行,非得把前 9 万行也搬进来。另一种是代码看着很“现代”,流一顿操作,最后边界没兜住,文件连 10 行都没有直接炸。

这题其实没什么花活,顺着读就行。读到第 10 行就停,别多看一眼。现场里我一般就这么写,因为这种代码最稳,日志脚本、配置巡检、小工具都能直接复用。

先上最朴素也最顺手的一版:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

publicclassTenthLineReader{

publicstatic String readTenthLine(String filePath){
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
int lineNo = 0;
while ((line = reader.readLine()) != null) {
                lineNo++;
if (lineNo == 10) {
return line;
                }
            }
return"";
        } catch (IOException e) {
thrownew IllegalStateException("读取文件失败: " + filePath, e);
        }
    }

publicstaticvoidmain(String[] args){
        String filePath = "file.txt";
        String result = readTenthLine(filePath);
        System.out.println(result);
    }
}

这段代码的意思很直接:

读一行,计一次数。

数到 10,就返回。

如果文件压根没到 10 行,返回空串。

这种写法看着普通,但现场真好用。因为它有两个优点:第一,内存稳;第二,出问题时容易补日志。很多人刷题时嫌这种写法“笨”,我倒不这么看。代码这玩意儿,在线上能少绕一层就少绕一层。

比如你后面真要排查一个线上配置文件,怀疑第 10 行有脏数据,我大概率还会顺手加点这种输出:

publicstatic String readTenthLineWithTrace(String filePath){
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
        String line;
int lineNo = 0;
while ((line = reader.readLine()) != null) {
            lineNo++;
if (lineNo <= 10) {
                System.out.println("scan line " + lineNo + ": " + line);
            }
if (lineNo == 10) {
return line;
            }
        }
        System.out.println("file has less than 10 lines");
return"";
    } catch (IOException e) {
thrownew RuntimeException("read file error, path=" + filePath, e);
    }
}

这就不是为了刷题好看了,这是为了出事的时候别瞎猜。

再往下说一句,这题真正的点不在“怎么读文件”,而在“有没有必要把问题做复杂”。有些题你得上动态规划,有些题你第一眼就该克制。第十行这种题,你只要记住一句话:需求是拿第 10 行,不是分析整个文件。

所以别一上来:

  • Files.readAllLines()
  • List<String> all = ...
  • all.get(9)

能用,但不划算。文件小的时候你感觉不到,文件大一点,这种写法就开始别扭了。尤其在服务里处理上传文本、批量日志、导出结果时,这种“先全读再说”的习惯挺容易把自己坑了。

最后补个边界:

如果题目要求“没有第 10 行就输出空”,那上面的代码就够了。

如果要求“没有第 10 行就抛异常”,那把返回空串改成异常即可。

如果输入是标准输入流,不是文件路径,那就把 FileReader 换成 InputStreamReader(System.in),主体逻辑都不用动。

这题不难,难的是别写过头。很多时候,能在第 10 行停下来的代码,比能把 10 万行都处理完的代码更像是干活的人写的。