【发布时间】:2020-12-30 11:11:53
【问题描述】:
我正在尝试制作一个程序,该程序使用数据来寻找大型 3D 数学网络的解决方案。在 JSON 格式中,有一个节点数组和关于它们在 3D 空间中的位置以及它们具有哪些属性等的信息,使用行分隔格式:
{"ID": 1, "Type": "Node", "OtherInfo":["info1", "info2"], "x": 0, "y": 0, "z": 0}
{"ID": 2, "Type": "OtherNode", "OtherInfo":["otherinfo1", "otherinfo2"], "x": 1, "y": 0, "z": 0}
...
我的班级:
class Node
{
ulong ID { get; set; }
nodeType Type { get; set; }
string[] otherInfo { get; set; }
decimal X { get; set; }
decimal Y { get; set; }
decimal Z { get; set; }
}
我的获取方法:
public static IEnumerable<Node> ReadStream(Stream stream)
{
var serializer = new JsonSerializer();
using var reader = new StreamReader(stream);
using var jsonReader = new JsonTextReader(reader) { SupportMultipleContent = true };
Stopwatch foo = new Stopwatch();
bool ll = jsonReader.Read();
while (ll)
{
Node node = null;
try
{
node = serializer.Deserialize<Node>(jsonReader);
ll = jsonReader.Read();
}
catch (Exception e)
{
Console.WriteLine($"Exception {e}");
continue;
}
yield return node;
}
}
我将变量 var stream = await HttpClient.GetStreamAsync("https://example.com/nodes.jsonl"); 传递给函数,它大多数运行良好,每 1/50000 个节点失败一次。问题是一旦失败,在 65,000 个节点中,它会开始读取 "info1" 和 "otherinfo1" 作为需要对未能反序列化的对象进行反序列化的节点。
Exception Newtonsoft.Json.JsonSerializationException: Error converting value "info1" to type 'Starbreaker.Node'. Path 'type', line 61876, position 295. ---> System.ArgumentException: Could not cast or convert from System.String to Starbreaker.Node.
at Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable(Object value, Type initialType, Type targetType)
at Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(Object initialValue, CultureInfo culture, Type targetType)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
--- End of inner exception stack trace ---
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)
at Starbreaker.settings.<ReadStream>d__1.MoveNext() in C:\repos\Starbreaker\Starbreaker\Form1.cs:line 361
这是我得到的网络错误之一:
Exception System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.ConnectStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.Net.Http.DelegatingStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.StreamReader.ReadBuffer(Char[] userBuffer, Int32 userOffset, Int32 desiredChars, Boolean& readToUserBuffer)
at System.IO.StreamReader.Read(Char[] buffer, Int32 index, Int32 count)
at Newtonsoft.Json.JsonTextReader.ReadData(Boolean append, Int32 charsRequired)
at Newtonsoft.Json.JsonTextReader.ReadStringIntoBuffer(Char quote)
at Newtonsoft.Json.JsonTextReader.ParseProperty()
at Newtonsoft.Json.JsonTextReader.ParseObject()
at Newtonsoft.Json.JsonTextReader.Read()
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)
at Starbreaker.settings.<ReadStream>d__1.MoveNext() in C:\repos\Starbreaker\Starbreaker\Form1.cs:line 361
无论是否有错误,读取功能似乎都会移动位置。发生网络错误时,是否有办法将其移回行首,或者是否有其他方法可以解决此问题?
【问题讨论】: