【问题标题】:Can I send an obj of a class to a file using filestream in C#?我可以使用 C# 中的文件流将类的 obj 发送到文件吗?
【发布时间】:2014-04-15 08:33:39
【问题描述】:

我想知道是否可以发送一个包含 4 个成员的整个 obj:

string name
string lastname
int StudentID
int CitizenID

使用文件流命令以二进制格式保存在 .txt 文件中?

我知道序列化,它很容易将一个 obj 发送到一个 .xml 文件,但是当我使用它制作我的程序并将它展示给我的老师时,他说他不想让我使用它,说我必须在 C++ 中使用 fstream、instream、outstream 和 ... 等基本文件流命令,并告诉我他希望以二进制格式保存 .txt 文件。

现在我的问题是,我可以将整个 obj 发送到 C# 中的 .txt 文件还是必须像字符串一样发送它,这将是很多工作。

因为我必须将所有成员转换为字符串,然后在每个成员的末尾放置一个指示符或其他东西,以便我以后可以读取它们并将它们分开。

【问题讨论】:

  • 他希望用 C++ 而不是 C# 来完成?这是要澄清的重要的第一部分。您的问题被标记为 C#,并且您问是否可以将对象发送到 C# 中的文本文件,但是如果您的老师只会说“不,我告诉您用 C++ 来做”,那么您在这里得到的任何帮助有什么用?请澄清:您需要在 C# 或 C++ 中完成此操作吗?
  • 我质疑保存为二进制格式并附加 .TXT 文件扩展名的有效性。如果您使用二进制序列化机制,您将无法打开文件并在记事本中正确读取它。所有文件都是二进制文件,它们由字节组成。具有 .TXT 扩展名是一个信号,它告诉程序这个由字节组成的文件在某种程度上可以被解释为由字符组成的文本。但是仅仅附加 .TXT 并不能使它成为文本或可读的。
  • @LasseV.Karlsen,嘿,他不想用 C++,他说随心所欲,但他在这堂课之前是我们的 C++ 老师,所以他告诉我我想要你使用 fstream instream outstream 以及你在 C++ 中使用或在 C# 中为你的程序均衡它们,并使二进制 .txt 文件不是 .xml
  • @LasseV.Karlsen 和 yeh ,我知道我无法在记事本等中打开它,但我应该可以用我的程序再次打开它,这样我就可以搜索记录和如果需要,编辑或删除它们。
  • @Pedram 注意:在文件内编辑和删除(无需重写整个文件)并不像您想象的那么简单,如果这是您需要设计的实际需求.例如,固定长度的记录或填充,以及可能的逻辑删除标志。或逻辑删除(设置一位)并附加到文件末尾等。

标签: c# io filestream


【解决方案1】:

现在我的问题是,我可以将整个 obj 发送到 C# 中的 .txt 文件还是必须像字符串一样发送...这将是很多工作,

是的,有一个名称:序列化。无论您是在自己的代码中手动执行,还是使用一系列现有序列化库中的一个,它都是序列化。如果您的老师不希望您使用序列化库,那么您必须在自己的代码中进行。坦率地说,这是愚蠢的。我想知道老师是否希望你也将原始命令写入硬盘,以避免所有那些愚蠢的抽象,如 HAL、OS 或通用类库......

可能值得与您的老师确切地澄清什么是可接受的,什么是不可接受的。例如,二进制序列化器就足够了吗?我可以说出几个。使用BinaryWriter/BinaryReader可以吗?或者练习的目的是让您考虑序列化/反序列化需要做什么?如果是后者:那么是的,了解流、编码和帧协议(标记值与长度前缀数据等)。

【讨论】:

  • 是的,我知道序列化,我想我的老师想要 .txt 二进制文件,他很酷,直到他认为它产生 .xml 文件,他告诉我制作一个二进制 .txt 文件有我的学生记录保存在上面,整个问题正在制作一个程序,将学生记录保存到文件中,然后搜索,编辑,删除它,当我问他如何将它们分开时,他说制作一个字符串并将其打印为每条记录的最后一行,所以你知道它结束了,新记录开始了,比如双 00 之类的,
  • “我的老师想要 .txt 二进制文件”——基本上,请允许我重复 Lasse 已经说过的一切;光是这句话就让我胆战心惊。但实际上,如果您的想法是让您了解如何将数据写入文件,那就去做吧。
  • 顺便说一句,我不知道我所拥有的这个类在英语中的确切名称,但如果你逐字翻译它,它将是:数据的存储和检索
  • 大声笑我的意思是我的老师想要一个包含以二进制格式写入数据的 something.txt 文件,在 C++ 中,你会在其末尾添加类似 IOS:Binary 或其他内容,它会保存作为二进制!
  • @Pedram 不,除非您在协议中提供了这一点。文件位置只是一个偏移量。例如,考虑一张 CD。 “移至轨道 9”是什么意思?它之所以有意义,是因为有一些索引数据可以定义第 9 轨。没有它,您必须手动搜索。
【解决方案2】:

我会用这个...

void saveInBinary()
{
    IFormatter binaryFormatter = new BinaryFormatter();
    Stream binaryStream = new FileStream("File Path Here", FileMode.Create, FileAccess.Write, FileShare.None);
    binaryFormatter.Serialize(binaryStream, this);
    binaryStream.Close();
}

将其粘贴在对象的成员空间中,然后调用它。

或者,一些更有用的东西......

void saveInBinary(object o)
{
    IFormatter binaryFormatter = new BinaryFormatter();
    Stream binaryStream = new FileStream("File Path Here", FileMode.Create, FileAccess.Write, FileShare.None);
    binaryFormatter.Serialize(binaryStream, o);
    binaryStream.Close();
}

这将序列化任何传递给它的对象。

最后的变化(我保证!):p

void saveInBinary(object o, string filePath)
{
    IFormatter binaryFormatter = new BinaryFormatter();
    Stream binaryStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
    binaryFormatter.Serialize(binaryStream, o);
    binaryStream.Close();
}

这个允许你将一个对象和一个文件路径传递给方法,以将传递的对象序列化为传递的文件路径。

当然,这将不允许您读取 .txt 文件的内容。它看起来像mumbo jumbo。如果您的意图是将数据写入人类可读的文件,那么有很多示例。 :p 我只是提供了序列化的东西,因为我花了一段时间才弄明白。 ;)

编辑:射击。我忘记了一些代码...

using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

代码需要那些才能工作(对于 IFormatter)此外,要让 Stream 工作,您需要使用

using System.IO;

抱歉忘记了。

编辑 2:忘了提及,您需要在您希望以这种方式序列化的对象上使用 [Serializeable] 标记。只需将“[Serializeable]”放在要序列化的类的顶部即可。

[Serializeable]
class SerializeableObject
{
    string aString;

    void aMethod()
    {
    }
}

像这样。

【讨论】:

  • 嘿伙计,抱歉回复晚了,你的代码看起来不错,我实际上想要一个 mundo jumbo 不可读风格的文件,但我在运行时遇到了一些未处理的异常等,我通过了它们并且它工作得很好,但是我现在可以用什么代码来检索它并从这个文件中读回我的 obj 并在程序中使用它?
  • 修复了错误,我的班级需要 [Serializable] 和 [NonSerializable] 代码。
  • 糟糕,抱歉。我忘了包括那个。我现在已经解决了,哈哈。对此感到抱歉。
猜你喜欢
  • 2012-11-03
  • 1970-01-01
  • 2022-01-10
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
相关资源
最近更新 更多