【问题标题】:File I/O in Every Programming Language [closed]每种编程语言中的文件 I/O [关闭]
【发布时间】:2011-04-02 01:50:03
【问题描述】:

这一定是所有程序员不时都会遇到的一个常见问题。 如何从文本文件中读取一行?然后下一个问题总是我如何写回来。

当然,你们中的大多数人在日常编程中使用高级框架(可以在答案中使用),但有时也很高兴知道如何在低级进行。

我自己知道如何在 CC++Objective-C 中做到这一点,但如果只是为了帮助我们做出更好的决定,看看它在所有流行语言中是如何完成的肯定会很方便关于用什么语言来做我们的文件 io。特别是我认为看看它是如何在字符串操作语言中完成的会很有趣,比如:pythonruby,当然还有perl

所以我想在这里我们可以创建一个社区资源,我们都可以star到我们的个人资料和指我们何时需要用某种新语言进行文件 I/O。更不用说我们都会接触到我们每天都不会处理的语言。

你需要这样回答:

  1. 创建一个名为“fileio.txt”的新文本文件
  2. 将第一行“hello”写入文本文件。
  3. 将第二行“world”附加到文本文件中。
  4. 将第二行“world”读入输入字符串。
  5. 将输入字符串打印到控制台。

澄清:

  • 您应该仅针对每个答案展示如何使用一种编程语言进行此操作。
  • 假设文本文件事先不存在
  • 写完第一行不需要重新打开文本文件

对语言没有特别限制。 CC++C#JavaObjective-C 都很棒。

如果您知道如何在PrologHaskellFortranLispBasic 中操作,请继续。

【问题讨论】:

  • 这个问题是它不会出现在搜索特定语言的搜索中,因为它不是也不能被标记为每种语言。
  • 我不明白为什么这个问题被关闭了。这个网站的目的不就是帮助人们查找信息吗?如果有人知道如何在 C 中做某事(如 IO),并且想学习如何在 Python 中做同样的事情,这可以帮助他们同时看到两者。
  • 我也不明白为什么关闭。似乎只是因为它不包含“......在最少数量的字符中......”这很愚蠢。代码高尔夫是一项有趣的运动。但是,让所有的罗塞塔石问题在所有答案中都变得模糊、微小的代码真的有用吗?
  • 我不明白这如何适合问答网站:至少对于代码高尔夫,有一个客观的标准来对答案进行投票:最短或最聪明的答案获得最多选票。有了这个:它是什么,有多少人喜欢 Haskell?像这样的问题就像试图将每一种可能的内容类型硬塞进一个只为一个而设计的系统中。互联网的其他部分处理这个问题有什么问题?
  • 为什么这不起作用。没有关于每种方法的优缺点的信息(哪些语言只支持一种方法?)。没有讨论每种语言的权衡和深层问题。范围有限,这意味着需要一个 bajiliion 单独的“每种语言”问题。最重要的是,每个答案的质量都没有社区审核。当人们投票给他们时,为什么我说没有节制?因为每种语言应该只有一个答案,而且人们不会阅读足够多的答案来查看他们所在领域的多种选择。

标签: file-io language-agnostic programming-languages


【解决方案1】:

LOLCODE

The specs 至少可以说是粗略的,但我已尽力而为。让投票开始吧! :) 我仍然觉得这是一个有趣的练习。

HAI
CAN HAS STDIO?
PLZ OPEN FILE "FILEIO.TXT" ITZ "TehFilez"?
    AWSUM THX
        BTW #There is no standard way to output to files yet...
        VISIBLE "Hello" ON TehFilez
        BTW #There isn't a standard way to append to files either...
        MOAR VISIBLE "World" ON TehFilez
        GIMMEH LINES TehLinez OUTTA TehFilez
        I HAS A SecondLine ITZ 1 IN MAH TehLinez
        VISIBLE SecondLine
    O NOES
        VISIBLE "OH NOES!!!"
KTHXBYE

【讨论】:

  • 我认为没有任何其他语言可以拥有这个属性,从字面上看,让我......哈哈。
  • 我觉得 LOLCODE 比我见过的其他任何东西都更具可读性,这很遗憾吗?
  • 有趣的是,它有多么像一种自然语言。
  • 说你希望被否决是对 SO 投赞成票的保证,因为逆向心理是程序员的一种反射行为。
  • PLZ ? / AWSUM THX / O NOES 真是太棒了。这对我来说似乎有点全能。
【解决方案2】:

Python 3

with open('fileio.txt', 'w') as f:
   f.write('hello')
with open('fileio.txt', 'a') as f:
   f.write('\nworld')
with open('fileio.txt') as f:
   s = f.readlines()[1]
print(s)

澄清

  • readlines() 返回文件中所有行的list。 因此,调用 readlines() 会读取文件的每一行。 在这种特殊情况下,使用 readlines() 很好,因为无论如何我们都必须读取整个文件(我们想要它的最后一行)。 但是如果我们的文件包含很多行并且我们只想打印它的第 n 行,则没有必要读取整个文件。 以下是一些在 Python 中获取文件第 n 行的更好方法:What substitutes xreadlines() in Python 3?

  • 这是什么with语句? with 语句启动一个代码块,您可以在其中使用变量 f 作为调用 open() 返回的 stream object。 当 with 块结束时,python 会自动调用 f.close()。 这保证了当您退出 with 块时文件将被关闭,无论您如何或何时退出该块 (即使您通过未处理的异常退出它)。您可以显式调用 f.close(),但是如果您的代码引发异常并且您没有进行 f.close() 调用怎么办?这就是 with 语句很有用的原因。

  • 您无需在每次操作之前重新打开文件。您可以将整个代码写在一个带有块的代码中。

    with open('fileio.txt', 'w+') as f:
        f.write('hello')
        f.write('\nworld')
        s = f.readlines()[1]
    print(s)
    

    我使用了三个 with 块来强调三个操作之间的区别: 写入(模式'w'),追加(模式'a'),读取(模式'r',默认值)。

【讨论】:

  • 我真的认为任何人都不应该在示例代码中写readlines()[1]。在这种情况下,您可能知道该文件只有两行,但其他人兴高采烈地认为这是一个很好的解决方案可能会在一个百万行的文件上尝试它并得到一个相当令人讨厌的惊喜。
  • @Porculus 和 readlines() 我们不会遍历文件中的所有行。这是 python 3。 readlines() 返回一个迭代器(不是列表)。因此,只会读取文件的前两行。这类似于 python 2 中的 xreadlines() (在 python 3 中不存在)。
  • @snakile:您能否引用一些内容来支持 readlines() 返回一个迭代器(不是列表) 请注意:您通常不能索引迭代器。跨度>
  • @SilentGhost 我引用了“深入 Python 3”:“readlines() 方法现在返回一个迭代器,因此它与 Python 2 中的 xreadlines() 一样高效”。在以下位置搜索此声明:diveintopython3.org/porting-code-to-python-3-with-2to3.html。其次,在 python 3 中,您可以索引一个迭代器。在 shell 中键入 range(10)[4] (range() 在 Python 3 中也返回一个迭代器,这与 Python 2 中的 range() 返回一个列表相反)。请注意 range(N)[i] 是在 O(i) 中完成的,而不是 O(1) 也不是 O(N)。
  • @snakile:你的 cmets 在几个层面上都是错误的。首先,readlines 在 Python 3 中返回一个列表(测试并查看)。所以给出的代码将读取整个文件。其次,迭代器不能在 Python 2 或 3 中被索引。range 对象对索引有特殊的支持,这是在 O(1) 中完成的。
【解决方案3】:

大脑***k

,------------------------------------------------>,------------------------------------------------>,------------------------------------------------>[-]+++++++++>[-]+++++++++>[-]+++++++++<<<<<[>>>>>>+>>>+<<<<<<<<<-]>>>>>>>>>[<<<<<<<<<+>>>>>>>>>-]<<<<<<<<[>>>>>>+>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<<<[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]>>[-]<<<<<<<<[>>>>>>+>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<<<<->>>->>>>>[-]<<<<<<<<[>>>>>>+>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>][-]<<<<<<<[>>>>>+>>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<<<->>>->>>>[-]<<<<<<<[>>>>>+>>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>][-]<<<<<<[>>>>+>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<<->>>->>>[-]<<<<<<[>>>>+>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>]<[-]+<[-]+<<<<<<[>>>>>>[-]<<<<<<[-]]>>>>>>[[-]+<<<<<[>>>>>[-]<<<<<[-]]>>>>>[[-]+<<<<[>>>>[-]<<<<[-]]>>>>[[-]+<<<[>>>[-]<<<[-]]>>>[[-]+<<[>>[-]<<[-]]>>[[-]+<[>[-]<[-]]>[[-]+++++++++++++++++++++++++++++++++++++++++++++++++.-...>[-]<[-]]<>[-]]<<>>[-]]<<<>>>[-]]<<<<>>>>[-],------------------------------------------------>,------------------------------------------------>,------------------------------------------------>[-]+++++++++>[-]+++++++++>[-]+++++++++<<<<<[>>>>>>+>>>+<<<<<<<<<-]>>>>>>>>>[<<<<<<<<<+>>>>>>>>>-]<<<<<<<<[>>>>>>+>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<<<[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]>>[-]<<<<<<<<[>>>>>>+>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<<<<->>>->>>>>[-]<<<<<<<<[>>>>>>+>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>][-]<<<<<<<[>>>>>+>>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<<<->>>->>>>[-]<<<<<<<[>>>>>+>>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>][-]<<<<<<[>>>>+>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<<->>>->>>[-]<<<<<<[>>>>+>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>]<[-]+<[-]+<<<<<<[>>>>>>[-]<<<<<<[-]]>>>>>>[[-]+<<<<<[>>>>>[-]<<<<<[-]]>>>>>[[-]+<<<<[>>>>[-]<<<<[-]]>>>>[[-]+<<<[>>>[-]<<<[-]]>>>[[-]+<<[>>[-]<<[-]]>>[[-]+<[>[-]<[-]]>[[-]+++++++++++++++++++++++++++++++++++++++++++++++++.-...>[-]<[-]]<>[-]]<<>>[-]]<<<>>>[-]]<<<<>>>>[-]]<<<<<>>>>>[-]]<<<<<<>>>>>>>[<<<<<<<<[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]>[-]++++++++++<<+<<<<<<+>>>>>>>>>>>[-]<<<<<[>>>+>>+<<<<<-]>>>>>[<<<<<+>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<->>->>>[-]<<<<<[>>>+>>+<<<<<-]>>>>>[<<<<<+>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>]<<<<[-]+<[>[-]<[-]]>[[-]+>[<[-]>[-]]<[<<<<<<<[-]<+>>>>>>>>[-]]><[-]]<<<<<<<<[>>>>>>+>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]>[-]++++++++++>>>[-]<<<<<<[>>>>+>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<<->>>->>>[-]<<<<<<[>>>>+>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>]<<<<[-]+<<[>>[-]<<[-]]>>[[-]+>[<[-]>[-]]<[<<<<<<<<[-]<+>>>>>>>>>[-]]><[-]]<<<<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>>>[-]]]<<<<<>>>>>[-]]<<<<<<>>>>>>>[<<<<<<<<[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]>[-]++++++++++<<+<<<<<<+>>>>>>>>>>>[-]<<<<<[>>>+>>+<<<<<-]>>>>>[<<<<<+>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<->>->>>[-]<<<<<[>>>+>>+<<<<<-]>>>>>[<<<<<+>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>]<<<<[-]+<[>[-]<[-]]>[[-]+>[<[-]>[-]]<[<<<<<<<[-]<+>>>>>>>>[-]]><[-]]<<<<<<<<[>>>>>>+>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]>[-]++++++++++>>>[-]<<<<<<[>>>>+>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>[<<<<<<->>>->>>[-]<<<<<<[>>>>+>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<[>>+>+<<<-]>>>[<<<+>>>-][-]<<[>>[-]<[>[-]+<[-]]<[-]]>[-]>]<<<<[-]+<<[>>[-]<<[-]]>>[[-]+>[<[-]>[-]]<[<<<<<<<<[-]<+>>>>>>>>>[-]]><[-]]<<<<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>>>[-]]

【讨论】:

  • 你错过了一个'-'吗? ;)
  • 哦,辛苦了。仅作记录,写了多少时间?
  • 你不能把它分成多行吗?有史以来最好的语言
【解决方案4】:

COBOL

因为没有人这样做......

IDENTIFICATION DIVISION.
PROGRAM-ID.  WriteDemo.
AUTHOR.  Mark Mullin.
* Hey, I don't even have a cobol compiler

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT StudentFile ASSIGN TO "STUDENTS.DAT"
        ORGANIZATION IS LINE SEQUENTIAL.

DATA DIVISION.
FILE SECTION.
FD TestFile.
01 TestData.
   02  LineNum        PIC X.
   02  LineText       PIC X(72).

PROCEDURE DIVISION.
Begin.
    OPEN OUTPUT TestFile
    DISPLAY "This language is still around."

    PERFORM GetFileDetails
    PERFORM UNTIL TestData = SPACES
       WRITE TestData 
       PERFORM GetStudentDetails
    END-PERFORM
    CLOSE TestFile
    STOP RUN.

GetFileDetails.
    DISPLAY "Enter - Line number, some text"
    DISPLAY "NXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    ACCEPT  TestData.

【讨论】:

  • 这应该得到不少于 100 万次的投票才能获得纯粹的赞誉 +1
  • +1 表示“这种语言仍然存在”。 =D
  • 在家里尝试这个时要小心。您的 cobol 编译器可能不喜欢这些现代的可变长度行...
  • 是的,这让我想起了一些生疏的旧回忆。我认为它不符合要求...
  • 我现在正在用 AcuCOBOL 编写代码!顺便问一下,“I/O”的“I”部分在哪里?
【解决方案5】:

哈斯克尔

main :: IO ()
main = let filePath = "fileio.txt" in
       do writeFile filePath "hello"
          appendFile filePath "\nworld"
          fileLines <- readFile filePath
          let secondLine = (lines fileLines) !! 1
          putStrLn secondLine

如果你只是想读/写一个文件:

main :: IO ()
main = readFile "somefile.txt" >>= writeFile "someotherfile.txt" 

【讨论】:

  • 啊,“全能”的 Haskell。感谢您的贡献:)
  • @Andreas Rejbrand 我几乎可以肯定他忘记了“be”
  • 在 Haskell 中还有许多其他的基本 I/O 方法,一旦你在做某些类型的应用程序,它们在 Haskell 中就会变得有用/重要。 cabal/hackage 上的 text 和 bytestring 包让您可以处理各种编码,而各种 iteratee 风格的包(例如 iteratee 和 enumerate)代表了用于执行增量 io 的“最知名的抽象”。同样重要的是解析像 parsec 这样的库和仅 attoparsec 库的增量字节串。 Haskellers 采取了非常彻底的方法来探索 io 设计选择。不可行的例子包括惰性 io 和延续
  • 虞姬:基本上,靠作弊。 Haskell 是一种纯函数式语言,except 适用于 IO a 类型的任何内容,它具有对副作用的特殊编译器支持。 (纯度保留在别处,因为执行或观察副作用的 anythingIO a 类型,因此类型系统确保程序的其余部分保持纯净。)
  • 碰巧IO 是一个单子,但这不是它允许产生副作用的原因。作为一个 monad 可以让你编写看起来像命令式的语法:它还确保(也有特殊的语言支持)副作用以合理的顺序发生,所以你在写入文件之前不要从文件中读取,等等.
【解决方案6】:

D

module d_io;

import std.stdio;


void main()
{
    auto f = File("fileio.txt", "w");
    f.writeln("hello");
    f.writeln("world");

    f.open("fileio.txt", "r");
    f.readln;
    auto s = f.readln;
    writeln(s);
}

【讨论】:

  • +1,比 C++ 版本更美观、更易读!我梦想有一天 D 完全取代 C 和 C++。 :-)
  • 不错。也许有一天我应该学习 D。
【解决方案7】:

红宝石

PATH = 'fileio.txt'
File.open(PATH, 'w') { |file| file.puts "hello" }
File.open(PATH, 'a') { |file| file.puts "world" }
puts line = File.readlines(PATH).last

【讨论】:

  • +1 不错,但严格来说,您不要在将输入写入控制台之前将其放入变量中。
  • @lasseespeholt,你是对的。我修好了。
  • 没有理由将 varname 大写并说 'PATH'。只需说“路径”即可。
  • @otz 这是一个常数。不过,他本可以将其称为“路径”,Ruby 中的常量只需以大写字母开头。
  • @Thomas Ahle:当File.open 与块一起使用时,文件被打开,传递给块,然后自动关闭。
【解决方案8】:

C#

string path = "fileio.txt";
File.WriteAllLines(path, new[] { "hello"}); //Will end it with Environment.NewLine
File.AppendAllText(path, "world");

string secondLine = File.ReadLines(path).ElementAt(1);
Console.WriteLine(secondLine);

File.ReadLines(path).ElementAt(1) 仅适用于 .Net 4.0,替代方案是 File.ReadAllLines(path)[1],它将整个文件解析为一个数组。

【讨论】:

  • 它在 C# 中相当短。感谢贡献
  • 注意:File.ReadLines 特定于 .NET 4
  • C# 有多么令人不快的语法
  • @Aiden Bell:相对于哪种语言?
  • @Aiden Bell - 这个答案试图简洁易读。在 C# 中有很多“好”的方法可以实现相同的目标。请参阅dotnetperls.com/file-handling 了解更实际的示例。
【解决方案9】:

ANSI C

#include <stdio.h>
#include <stdlib.h>

int /*ARGSUSED*/
main(char *argv[0], int argc) {
   FILE *file;
   char buf[128];

   if (!(file = fopen("fileio.txt", "w")) {
      perror("couldn't open for writing fileio.txt");
      exit(1);
   }

   fprintf(file, "hello");
   fclose(file);

   if (!(file = fopen("fileio.txt", "a")) {
      perror("couldn't opened for appening fileio.txt");
      exit(1);
   }

   fprintf(file, "\nworld");
   fclose(file);

   if (!(file = fopen("fileio.txt", "r")) {
      perror("couldn't open for reading fileio.txt");
      exit(1);
   }

   fgets(buf, sizeof(buf), file);
   fgets(buf, sizeof(buf), file);

   fclose(file);

   puts(buf);

   return 0;
}

【讨论】:

  • 不错的答案。感谢贡献 +1
  • 为什么要调用 fgets() 两次?
  • 因为第二行是我们要打印到标准输出的那一行
  • #include int main(void) { FILE file;字符缓冲区[128];文件 = fopen("fileio.txt", "w");如果(!文件)转到错误; fputs("你好\n", 文件); fflush(文件); fputs("世界\n", 文件); fclose(文件);文件 = fopen("fileio.txt", "r");如果(!文件)转到错误; fgets(buf, sizeof(buf), 文件); / 跳过 'hello' / fgets(buf, sizeof(buf), file); / 得到'单词' */ fclose(file); fputs(缓冲区,标准输出);返回0;错误:fputs("无法打开文件\n", stderr);返回 1; }
  • 原始 C 帖子中漂亮的干净编码(很多不错的错误检查)(这有点超出了长度)。
【解决方案10】:

Shell 脚本 (UNIX)

#!/bin/sh
echo "hello" > fileio.txt
echo "world" >> fileio.txt
LINE=`sed -ne2p fileio.txt`
echo $LINE

实际上sed -n "2p" 部分打印第二行,但问题要求将第二行存储在变量中然后打印,所以... :)

【讨论】:

  • 我不知道为什么,但我喜欢这个:)
  • 当然很重要。很好的答案,感谢您的贡献 +1
  • 为什么不将标准发送到 /dev/null?
  • 有一个更简单、更快的版本,只使用 shell 内置函数(而不是分叉一个单独的进程来调用 sed),这里:stackoverflow.com/questions/3538156/…
  • @Gumbo,那么你将如何获得第二行? LINE=`foo`foo 的输出捕获到变量LINE 中。
【解决方案11】:

Linux 上的 x86 汇编器 (NASM)

我已经 7 年没有接触过 asm,所以我不得不稍微使用 google 来破解它,但它仍然有效;)我知道它不是 100% 正确,但是嘿:D

好的,它不起作用。对不起这件事。虽然它最终打印了world,但它不是从文件中打印,而是从第27行设置的ecx中打印。

section .data
hello db 'hello',10
helloLen equ $-hello
world db 'world',10
worldLen equ $-world
helloFile db 'hello.txt'

section .text
global _start

_start:
mov eax,8
mov ebx,helloFile
mov ecx,00644Q
int 80h

mov ebx,eax

mov eax,4
mov ecx, hello
mov edx, helloLen
int 80h

mov eax,4
mov ecx, world
mov edx, worldLen
int 80h

mov eax,6
int 80h

mov eax,5
mov ebx,helloFile
int 80h

mov eax,3
int 80h

mov eax,4
mov ebx,1
int 80h

xor ebx,ebx
mov eax,1
int 80h

参考文献: http://www.cin.ufpe.br/~if817/arquivos/asmtut/quickstart.html

http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html

http://www.digilife.be/quickreferences/QRC/LINUX%20System%20Call%20Quick%20Reference.pdf

【讨论】:

  • 您要纠正它以使其 100% 有效吗?如果没有,请将其删除,以便工作版本可以取代它。
  • 有点好笑的是,本应该是高级语言的C语言的例子,居然和这个一样长... =)
  • @Jani:但至少它更容易理解。
  • 一开始以为是 DOS 的 :)
【解决方案12】:

JavaScript - node.js

首先,大量嵌套回调。

var fs   = require("fs");
var sys  = require("sys");
var path = "fileio.txt";

fs.writeFile(path, "hello", function (error) {
    fs.open(path, "a", 0666, function (error, file) {
        fs.write(file, "\nworld", null, "utf-8", function () {
            fs.close(file, function (error) {
                fs.readFile(path, "utf-8", function (error, data) {
                    var lines = data.split("\n");
                    sys.puts(lines[1]);
                });
            });
        });
    });
});

干净一点:

var writeString = function (string, nextAction) {
    fs.writeFile(path, string, nextAction);
};

var appendString = function (string, nextAction) {
    return function (error, file) {
        fs.open(path, "a", 0666, function (error, file) {
            fs.write(file, string, null, "utf-8", function () {
                fs.close(file, nextAction);
            });
        });
    };
};

var readLine = function (index, nextAction) {
    return function (error) {
        fs.readFile(path, "utf-8", function (error, data) {
            var lines = data.split("\n");
            nextAction(lines[index]);
        });
    };
};

var writeToConsole = function (line) {
    sys.puts(line);
};

writeString("hello", appendString("\nworld", readLine(1, writeToConsole)));

【讨论】:

  • @Ionut:感谢您的许多贡献 +1
  • @Dave,这不是浏览器中的 JS。我的意思是,在语法和语义上,它是相同的 JS,只是标准库不同。我使用了node.js 平台的stdlib。见nodejs.org
  • 这段代码急需继续。我能听到它的眼泪。
  • 行数和楼下的ASM方案差不多,是不是很可笑?
  • @Matt 是的,延续或 monad 在这里也会有所帮助。
【解决方案13】:

普通的 Lisp

(defun main ()
  (with-open-file (s "fileio.txt" :direction :output :if-exists :supersede)
    (format s "hello"))
  (with-open-file (s "fileio.txt" :direction :io :if-exists :append)
    (format s "~%world")
    (file-position s 0)
    (loop repeat 2 for line = (read-line s nil nil) finally (print line))))

【讨论】:

  • 对于一种叫做“lisp”的语言,应该包含更多的“s”字母:)
【解决方案14】:

PowerShell

sc fileio.txt 'hello'
ac fileio.txt 'world'
$line = (gc fileio.txt)[1]
$line

【讨论】:

  • 这很好很干净。是的 powershell。
  • 我同意你关于引用的逻辑。我删除它们的原因是我意识到这个脚本实际上是最紧凑的,所以我希望它更小 - 但我们让它清楚:)。并且使用gc 而不是cat 是有道理的:-) get-alias 首先给了我cat(我不经常使用PowerShell)。
  • 该死,还有更短的吗??
【解决方案15】:

Shell 脚本

这是一个仅使用内置命令的 shell 脚本,而不是像以前的响应那样调用外部命令,例如 sedtail

#!/bin/sh

echo hello > fileio.txt             # Print "hello" to fileio.txt
echo world >> fileio.txt            # Print "world" to fileio.txt, appending
                                    # to what is already there
{ read input; read input; } < fileio.txt  
                                    # Read the first two lines of fileio.txt,
                                    # storing the second in $input
echo $input                         # Print the contents of $input

在编写重要的 shell 脚本时,建议尽可能使用内置函数,因为生成单独的进程可能会很慢;通过在我的机器上进行的快速测试,sed 解决方案比使用read 慢大约 20 倍。如果你要调用sed 一次,在这种情况下,这并不重要,因为它的执行速度比你注意到的要快,但是如果你要执行它数百或数千次,可以加起来。

对于那些不熟悉语法的人,{} execute a list of commands in the current shell environment(与创建子 shell 的 () 相反;我们需要在当前的 shell 环境中操作,所以我们可以稍后使用变量的值)。我们需要将命令组合在一起,以使它们都在同一输入流上运行,该输入流是通过从fileio.txt 重定向创建的;如果我们简单地运行read &lt; fileio.txt; read input &lt; fileio.txt,我们只会得到第一行,因为文件将在两个命令之间关闭并重新打开。由于 shell 语法的特殊性({} 是保留字,而不是元字符),我们需要用空格将 {} 与其余命令分开,并终止列表带有; 的命令。

read builtin 将要读取的变量名称作为参数。它消耗一行输入,用空格打断输入(从技术上讲,它根据$IFS的内容打断它,默认为空格字符,其中空格字符表示将其拆分为空格、制表符或换行符中的任何一个),将每个单词分配给按顺序给出的变量名,并将该行的其余部分分配给最后一个变量。由于我们只提供一个变量,因此它只是将整行放入该变量中。我们重用了$input 变量,因为我们不关心第一行的内容(如果我们使用 Bash,我们不能提供变量名,但为了便于移植,您必须始终提供至少一个名称)。

请注意,虽然您可以一次读取一行,就像我在这里所做的那样,但更常见的模式是将其包装在 while 循环中:

while read foo bar baz
do
  process $foo $bar $baz
done < input.txt

【讨论】:

  • 非常好。我学到了一些东西(虽然是暂时的)。
  • 感谢布赖恩的贡献。
  • 病了!以一种好的方式:-)
【解决方案16】:

Clojure

(use '[clojure.java.io :only (reader)])

(let [file-name "fileio.txt"]
  (spit file-name "hello")
  (spit file-name "\nworld" :append true)
  (println (second (line-seq (reader file-name)))))

或者等效地,使用线程宏-&gt;(也称为paren remover):

(use '[clojure.java.io :only (reader)])

(let [file-name "fileio.txt"] 
  (spit file-name "hello") 
  (spit file-name "\nworld" :append true) 
  (-> file-name reader line-seq second println))

【讨论】:

  • WTF,在过去的 50 年里几乎没有人说 Lisp/Scheme 摇滚!
  • 等等,spit真的是写入文件函数的名字吗?
  • Clojure 绝对不会摇滚!
  • @[Sam Stokes] 核心中有一个名为 slurp 的函数,它将整个文件读入字符串并返回。 spit 正好相反。有什么问题?还有其他函数,比如 line-seq,以不同的方式做类似的事情。
  • @kirk.burleson 当然比 Java 更震撼。 :)
【解决方案17】:

F#

let path = "fileio.txt"
File.WriteAllText(path, "hello")
File.AppendAllText(path, "\nworld")

let secondLine = File.ReadLines path |> Seq.nth 1
printfn "%s" secondLine

【讨论】:

  • F#。好的。感谢您的贡献。
【解决方案18】:

基本

我已经快 10 年没有使用 BASIC 了,但是这个问题给了我一个快速复习知识的理由。 :)

OPEN "fileio.txt" FOR OUTPUT AS 1
PRINT #1, "hello"
PRINT #1, "world"
CLOSE 1

OPEN "fileio.txt" FOR INPUT AS 1
LINE INPUT #1, A$
LINE INPUT #1, A$
CLOSE 1

PRINT A$

【讨论】:

  • 10 年后你还能做到这一点真是太棒了!做得好,感谢您的贡献。
  • 我当然不是一时兴起:花了几分钟查了些东西。
  • 是的,当然。还是做得很好。
  • BASIC最经典的版本不需要行号吗???
  • @Yuji:在“最经典的版本”中,是的,但我认为90年代初期以来的任何版本都不需要它们。
【解决方案19】:

Objective-C

NSFileHandle *fh = [NSFileHandle fileHandleForUpdatingAtPath:@"fileio.txt"];

[[NSFileManager defaultManager] createFileAtPath:@"fileio.txt" contents:nil attributes:nil];

[fh writeData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding]];
[fh writeData:[@"\nworld" dataUsingEncoding:NSUTF8StringEncoding]];

NSArray *linesInFile = [[[NSString stringWithContentsOfFile:@"fileio.txt" 
                                             encoding:NSUTF8StringEncoding 
                                                error:nil] stringByStandardizingPath] 
                          componentsSeparatedByString:@"\n"];

NSLog(@"%@", [linesInFile objectAtIndex:1]);

【讨论】:

  • 我从不喜欢 Objective-C。来自像 Java 这样的语言时,语法看起来很陌生。
  • Objective-C 的秘密在于 Xcode 会为您完成所有代码。您不必记住长方法名称。虽然它们确实使您的代码更具可读性
  • 我认为 c++ 语法看起来已经很糟糕了。
  • Objective-C 看起来很糟糕,因为 Stackoverflow 语法荧光笔没有正确着色。
  • 我不敢相信这是排在列表后面的!还有 Java 人评论说 Objective-C 很丑,你看到写同一个文件需要多少行吗?我曾经是一名 Java 爱好者,但我认为 Objective-C 已经深入我的内心。
【解决方案20】:

Perl

#!/usr/bin/env perl

use 5.10.0;
use utf8;
use strict;
use autodie;
use warnings qw<  FATAL all     >;
use open     qw< :std  :utf8    >;

use English  qw< -no_match_vars >;

# and the last shall be first
END { close(STDOUT) }

my $filename = "fileio.txt";
my($handle, @lines);

$INPUT_RECORD_SEPARATOR = $OUTPUT_RECORD_SEPARATOR = "\n";

open($handle, ">",  $filename);
print $handle "hello";
close($handle);

open($handle, ">>", $filename);
print $handle "world";
close($handle);

open($handle, "<",  $filename);
chomp(@lines = <$handle>);
close($handle);

print STDOUT $lines[1];

【讨论】:

  • 词法文件句柄如何,3 个参数打开?
  • 不应该在 Stack Overflow 上使用非词法文件句柄。在实践中很少需要它们,而且初学者也不应该被证明它们甚至存在。
  • 打开两个参数也是如此:你永远不应该在 Stack Overflow 上使用它,而且可能不会在实践中使用它。
  • 我经常使用 3-arg 开放式和词法文件句柄,当我看到它时,我几乎认为它是语法错误。应该是这样。 /me 考虑编写一个模块来实现它。
  • “即使一元开放也有它的用途”,它有它的用途,是的,但是当我弄清楚它是如何工作的那一天,我感到被滥用了,并且每次我都会去“肯定还有另一种方式”看到认为他们需要它的人。 perl -we 'for (q{ps aux |}){ open _; print &lt;_&gt;; }'
【解决方案21】:

R:

cat("你好\n", file="fileio.txt") cat("world\n", file="fileio.txt", append=TRUE) line2 = readLines("fileio.txt", n=2)[2] 猫(第 2 行)

【讨论】:

    【解决方案22】:

    PHP

    <?php
    
    $filePath = "fileio.txt";
    
    file_put_contents($filePath, "hello");
    file_put_contents($filePath, "\nworld", FILE_APPEND);
    
    $lines = file($filePath);
    
    echo $lines[1];
    
    // closing PHP tags are bad practice in PHP-only files, don't use them
    

    【讨论】:

    • 太好了。感谢您的贡献。
    • 或者,您可以采用 C 实现并添加美元符号。
    • @strager 我不知道。有些人不知道它是可选的,没有它实际上会更好。
    • 以防万一有人好奇,他留下结束标签的原因是因为如果你包含它,并留下任何尾随空格,你可能会得到一个“标题已发送”错误。跨度>
    • 没有?&gt;的参考:framework.zend.com/manual/en/…
    【解决方案23】:

    Java

    import java.io.*;
    import java.util.*;
    
    class Test {
      public static void  main(String[] args) throws IOException {
        String path = "fileio.txt";
        File file = new File(path);
    
        //Creates New File...
        try (FileOutputStream fout = new FileOutputStream(file)) {
          fout.write("hello\n".getBytes());
        }
    
        //Appends To New File...
        try (FileOutputStream fout2 = new FileOutputStream(file,true)) {
          fout2.write("world\n".getBytes());
        }
    
        //Reading the File...
        try (BufferedReader fin = new BufferedReader(new FileReader(file))) {
          fin.readLine();
          System.out.println(fin.readLine());
        }       
      }
    }
    

    【讨论】:

    • @Brock:现在 Java 并不慢。只是冗长,但不慢。请不要制作这样的cmets;伤害了我们 JVM 的人。 :'|
    • 说 Java 慢的人要么是盲目的 Java 仇恨者,要么是生活在岩石之下。 Java 可以与 C 一样快,甚至比 C 还要快,并且可以独立于启动平台。
    • @Missing Faktor:然后呢?
    • 执行速度是程序员最迟钝的比赛形式。总是要为工作选择正确的工具,选择像执行速度这样的随机指标并为其分配重要的堆只是愚蠢的,特别是因为执行速度对于绝大多数任务来说并不是非常重要,只要它足够快(java 几乎适用于所有东西)
    • “硬接线比机器码快”、“机器码比 asm 快”、“asm 比 C 快”、“C 比 Java 快”、“等等等等”...您是否甚至知道机器代码和 CPU 之间已经存在多少间接性?微码、预测优化器、指令/数据缓存、解码器等,更不用说由 C/asm 中的动态分配引起的不确定性。 Java 和其他安全语言只是间接的一小步,没什么大不了的。您可以永远保持原始状态,也可以与我们一起进化。
    【解决方案24】:

    C++

    #include <limits>
    #include <string>
    #include <fstream>
    #include <iostream>
    
    int main() {
        std::fstream file( "fileio.txt",
            std::ios::in | std::ios::out | std::ios::trunc  );
        file.exceptions( std::ios::failbit );   
    
        file << "hello\n" // << std::endl, not \n, if writing includes flushing
             << "world\n";
    
        file.seekg( 0 )
            .ignore( std::numeric_limits< std::streamsize >::max(), '\n' );
        std::string input_string;
        std::getline( file, input_string );
    
        std::cout << input_string << '\n';
    }
    

    或者不那么迂腐,

    #include <string>
    #include <fstream>
    #include <iostream>
    using namespace std;
    
    int main() {
        fstream file( "fileio.txt", ios::in | ios::out | ios::trunc  );
        file.exceptions( ios::failbit );   
    
        file << "hello" << endl
             << "world" << endl;
    
        file.seekg( 0 ).ignore( 10000, '\n' );
        string input_string;
        getline( file, input_string );
    
        cout << input_string << endl;
    }
    

    【讨论】:

    • 太棒了!感谢贡献 +1
    • 我忘了 c++ 的语法有多难看。
    • 与大多数 C++ 代码的样子相比,这残暴的。主要问题是标准库中没有定义适当的常量,而不是语法。让我大吃一惊的是,我需要包含 &lt;limits&gt; 只是为了告诉 ignore 那里没有行大小的限制。
    • @Hans:你想澄清一下吗?就我个人而言,我认为 I/O 属于 库而不是语言,并且我编写的所有语言都是这样做的(C、C++、Java、Python 等)
    • 现在我知道为什么 Linus 说 C++ 丑陋了。 (无意冒犯)
    【解决方案25】:

    Go

    package main
    
    import (
      "os"
      "bufio"
      "log"
    )
    
    func main() {
      file, err := os.Open("fileio.txt", os.O_RDWR | os.O_CREATE, 0666)
      if err != nil {
        log.Exit(err)
      }
      defer file.Close()
    
      _, err = file.Write([]byte("hello\n"))
      if err != nil {
        log.Exit(err)
      }
    
      _, err = file.Write([]byte("world\n"))
      if err != nil {
        log.Exit(err)
      }
    
      // seek to the beginning 
      _, err = file.Seek(0,0)
      if err != nil {
        log.Exit(err)
      }
    
      bfile := bufio.NewReader(file)
      _, err = bfile.ReadBytes('\n')
      if err != nil {
        log.Exit(err)
      }
    
      line, err := bfile.ReadBytes('\n')
      if err != nil {
        log.Exit(err)
      }
    
      os.Stdout.Write(line)
    }
    

    【讨论】:

    • 此语言应重命名为“类型”
    • 对于 Go 中的基本文件 I/O 来说,os.O_RDWR | os.O_CREATE, 0666 垃圾是否必要?
    • 或者应该改名为“停止”
    • 令人惊讶的是,经过 30 年的发展和语言设计,他们仍然设法发明了一种新语言,这种语言与 C 语言一样难以编写错误检查代码。甚至 Java 也不那么冗长!
    • 哇... Go 似乎太失败了这个例子
    【解决方案26】:

    二郎

    可能不是最惯用的 Erlang,但是:

    #!/usr/bin/env escript
    
    main(_Args) ->
      Filename = "fileio.txt",
      ok = file:write_file(Filename, "hello\n", [write]),
      ok = file:write_file(Filename, "world\n", [append]),
      {ok, File} = file:open(Filename, [read]),
      {ok, _FirstLine} = file:read_line(File),
      {ok, SecondLine} = file:read_line(File),
      ok = file:close(File),
      io:format(SecondLine).
    

    【讨论】:

      【解决方案27】:

      Emacs Lisp

      尽管有人说 Emacs 主要是一个文本编辑器 [1]。因此,虽然 Emacs Lisp 可用于解决各种问题,但它针对文本编辑器的需求进行了优化。由于文本编辑器(显然)在处理文件时有非常特殊的需求,这会影响 Emacs Lisp 提供的与文件相关的功能。

      基本上这意味着 Emacs Lisp 不提供将文件作为流打开并逐部分读取的功能。同样,您不能在不先加载整个文件的情况下附加到文件。而是将文件完全 [2] 读入缓冲区 [3],进行编辑,然后再次保存到文件中。

      对于必须使用 Emacs Lisp 的任务,这是合适的,如果你想做一些不涉及编辑的事情,可以使用相同的功能。

      如果您想一遍又一遍地附加到文件,这会带来巨大的开销,但正如这里所展示的那样是可能的。实际上,您通常在写入文件之前手动或以编程方式完成对缓冲区的更改(只需在下面的示例中组合前两个 s 表达式)。

      (with-temp-file "file"
        (insert "hello\n"))
      
      (with-temp-file "file"
        (insert-file-contents "file")
        (goto-char (point-max))
        (insert "world\n"))
      
      (with-temp-buffer
        (insert-file-contents "file")
        (next-line)
        (message "%s" (buffer-substring (point) (line-end-position))))
      

      [1] 至少我不会称它为操作系统;一个替代的 UI 是的,一个操作系统没有。

      [2] 您只能加载文件的一部分,但这只能按字节指定。

      [3] 缓冲区既是一种在某种程度上类似于字符串的数据类型,也是“您在编辑文件时看到的东西”。编辑缓冲区时显示在窗口中,但缓冲区不一定对用户可见。

      编辑:如果您想看到插入到缓冲区中的文本,您显然必须使其可见,并在操作之间休眠。因为 Emacs 通常只在等待用户输入时重新显示屏幕(并且睡眠与等待输入不同),所以您还必须强制重新显示。在这个例子中这是必要的(用它代替第二个sexp);在实践中,我从来没有使用过 `redisplay' 甚至一次 - 所以是的,这很丑但是......

      (with-current-buffer (generate-new-buffer "*demo*")
        (pop-to-buffer (current-buffer))
        (redisplay)
        (sleep-for 1)
        (insert-file-contents "file")
        (redisplay)
        (sleep-for 1)
        (goto-char (point-max))
        (redisplay)
        (sleep-for 1)
        (insert "world\n")
        (redisplay)
        (sleep-for 1)
        (write-file "file"))
      

      【讨论】:

      • 非常感谢。是否有可能增强这一点,所以我实际上看到一个“幽灵”打开文件并输入它,就像某种宏一样?
      【解决方案28】:

      Windows 批处理文件 - 版本 #2

      @echo off
      echo hello > fileio.txt
      echo world  >> fileio.txt
      set /P answer=Insert: 
      echo %answer%  >> fileio.txt
      for /f "skip=1 tokens=*" %%A in (fileio.txt) do echo %%A
      

      为了解释最后一个可怕的查找循环,它假设文件中只有 hello(换行符)世界。所以它只是跳过第一行,只回显第二行。

      更新日志

      • 2 - 哎呀,一定是误读了要求,否则他们改变了我。现在从文件中读取最后一行

      【讨论】:

      • 整洁。感谢您的贡献。
      • 我将第 4 步)理解为从创建的文件中读取
      • @devio - 要求一定已经改变,或者我只是误读了它们......无论如何我会看看这样的解决方案是否存在
      【解决方案29】:

      斯卡拉:

      使用标准库:

      val path = "fileio.txt"
      val fout = new FileWriter(path)
      fout write "hello\n"
      fout.close()
      val fout0 = new FileWriter(path, true)
      fout0 write "world\n"
      fout0.close() 
      val str = Source.fromFile(path).getLines.toSeq(1)
      println(str)
      

      使用 Josh Suereth 的Scala-ARM Library

      val path = "fileio.txt"
      for(fout <- managed(new FileWriter(path))) 
        fout write "hello\n"
      for(fout <- managed(new FileWriter(path, true))) 
        fout write "world\n"
      val str = Source.fromFile(path).getLines.toSeq(1)
      println(str)      
      


      由于许多人使用相同的文件描述符来编写这两个字符串,我的回答中也包含了这种方式。

      使用标准库:

      val path = "fileio.txt"
      val fout = new FileWriter(path)
      fout write "hello\n"
      fout write "world\n"
      fout.close()
      val str = Source.fromFile(path).getLines.toSeq(1)
      println(str)
      

      使用 Josh Suereth 的Scala-ARM Library

      val path = "fileio.txt"
      for(fout <- managed(new FileWriter(path))){
        fout write "hello\n"
        fout write "world\n"
      }
      val str = Source.fromFile(path).getLines.toSeq(1)
      println(str)
      

      【讨论】:

      • 我认为使用 flush() 而不是 close() 会更好看...无需重新实例化 FileWriter。
      • @Radtoo:必须显示附加操作。这就是我这样做的原因。
      • @Radtoo:在查看了此线程中的其他答案后,我最终决定将这种方式包含在我的答案中。检查。 (虽然我没有删除原始代码。)
      • @Missing Faktor, getLines().toList() 应该是 getLines().toSeq 哪个是懒惰的?
      • @Elazar:好建议。谢谢。 :)
      【解决方案30】:

      时髦

      new File("fileio.txt").with { 
          write  "hello\n"
          append "world\n"   
          println secondLine = readLines()[1]
      }
      

      【讨论】:

      • 你在“world\n”部分作弊。它不是附加的,它只是写入同一个文件描述符。
      • 原帖中的第三条澄清声明“写完第一行后不需要重新打开文本文件”
      猜你喜欢
      • 1970-01-01
      • 2021-06-11
      • 1970-01-01
      • 2023-03-07
      • 2011-03-05
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多