ทำความเข้าใจกับการทำให้เป็นอันดับ


38

ฉันเป็นวิศวกรซอฟต์แวร์และหลังจากการสนทนากับเพื่อนร่วมงานฉันรู้ว่าฉันไม่มีความเข้าใจที่ดีเกี่ยวกับการจัดลำดับแนวคิด ดังที่ฉันเข้าใจว่าการทำให้เป็นอันดับเป็นกระบวนการของการแปลงเอนทิตีบางอย่างเช่นวัตถุใน OOP เป็นลำดับของไบต์ดังนั้นเอนทิตีดังกล่าวสามารถจัดเก็บหรือส่งต่อเพื่อการเข้าถึงในภายหลัง (กระบวนการของ

ปัญหาที่ฉันมีคือ: ไม่ใช่ตัวแปรทั้งหมด (ไม่ว่าจะเป็นแบบดั้งเดิมintหรือวัตถุคอมโพสิต) ที่แสดงโดยลำดับไบต์แล้ว (แน่นอนว่าเป็นเพราะเก็บไว้ในทะเบียนหน่วยความจำดิสก์ ฯลฯ )

ดังนั้นสิ่งที่ทำให้เป็นอันดับเช่นหัวข้อลึก ในการทำให้เป็นอนุกรมตัวแปรเราไม่สามารถนำไบต์เหล่านี้ในหน่วยความจำแล้วเขียนมันไปยังไฟล์ได้หรือไม่? ฉันพลาดอะไรไปบ้าง?


21
การทำให้เป็นอันดับอาจไม่สำคัญสำหรับวัตถุที่อยู่ติดกัน เมื่อค่าวัตถุถูกแสดงเป็นกราฟตัวชี้สิ่งต่าง ๆ จะยุ่งยากมากขึ้นโดยเฉพาะถ้ากราฟที่กล่าวมามีลูป
Chi

1
@chi: ประโยคแรกของคุณคือความเข้าใจผิดเล็กน้อยเนื่องจากไม่เกี่ยวข้อง คุณอาจมีกราฟที่เกิดขึ้นต่อเนื่องในหน่วยความจำและยังไม่ช่วยคุณในการจัดลำดับเนื่องจากคุณยังต้อง (a) ตรวจพบว่ามันเกิดขึ้นต่อเนื่องและ (b) แก้ไขตัวชี้ภายใน ฉันแค่พูดส่วนที่สองของสิ่งที่คุณพูด
Mehrdad

@ Mehrdad ฉันยอมรับความคิดเห็นของฉันไม่แม่นยำอย่างสมบูรณ์ด้วยเหตุผลที่คุณพูดถึง บางทีการใช้ตัวชี้ / การใช้ตัวชี้อาจเป็นความแตกต่างที่ดีกว่า (แม้ว่าจะไม่ถูกต้องสมบูรณ์ก็ตาม)
chi

7
คุณต้องกังวลเกี่ยวกับการเป็นตัวแทนในฮาร์ดแวร์ ถ้าฉันเรียงลำดับ int 4 bytesใน PDP-11 ของฉันจากนั้นลองและอ่านสี่ไบต์เดียวกันเหล่านั้นลงในหน่วยความจำบน macbook ของฉันพวกเขาไม่ใช่หมายเลขเดียวกัน (เพราะ Endianes) ดังนั้นคุณต้องทำให้ข้อมูลกลับสู่การเป็นตัวแทนคุณสามารถลบรหัสได้ (นี่คือการทำให้เป็นอนุกรม) วิธีที่คุณจัดลำดับข้อมูลยังมีการแลกเปลี่ยนความเร็ว / ความยืดหยุ่นของมนุษย์ / เครื่องอ่านได้
Martin York

ถ้าคุณใช้ Entity Framework กับคุณสมบัติการนำทางที่เชื่อมต่ออย่างล้ำลึก ในกรณีหนึ่งคุณอาจต้องการทำให้เป็นอนุกรมคุณสมบัติการนำทาง แต่ในอีกกรณีหนึ่งปล่อยให้เป็นโมฆะ (เพราะคุณจะโหลดวัตถุจริงนั้นอีกครั้งจากฐานข้อมูลตามรหัสที่อยู่ในวัตถุแม่ของคุณเป็นอนุกรม) นี่เป็นเพียงตัวอย่างเดียว มีมากมาย.
ErikE

คำตอบ:


40

หากคุณมีโครงสร้างข้อมูลที่ซับซ้อนการแสดงข้อมูลในหน่วยความจำตามปกติอาจกระจัดกระจายไปทั่วหน่วยความจำ (คิดว่าเป็นต้นไม้ไบนารีเช่น)

ในทางตรงกันข้ามเมื่อคุณต้องการเขียนลงดิสก์คุณอาจต้องการให้มีการแสดงเป็นลำดับ (หวังว่าสั้น) ของไบต์ที่ต่อเนื่องกัน นั่นคือสิ่งที่ทำให้เป็นอันดับสำหรับคุณ


27

ปัญหาที่ฉันมีคือ: ไม่ใช่ตัวแปรทั้งหมด (ไม่ว่าจะเป็นแบบดั้งเดิมเช่นวัตถุ int หรือคอมโพสิต) ที่แสดงด้วยลำดับไบต์แล้ว (แน่นอนว่าเป็นเพราะเก็บไว้ในหน่วยความจำหน่วยความจำดิสก์ ฯลฯ )

ดังนั้นสิ่งที่ทำให้เป็นอันดับเช่นหัวข้อลึก ในการทำให้เป็นอนุกรมตัวแปรเราไม่สามารถนำไบต์เหล่านี้ในหน่วยความจำแล้วเขียนมันไปยังไฟล์ได้หรือไม่? ฉันพลาดอะไรไปบ้าง?

พิจารณากราฟวัตถุใน C ที่มีโหนดที่กำหนดดังนี้:

struct Node {
    struct Node* parent;
    struct Node* someChild;
    struct Node* anotherLink;

    int value;
    char* label;
};

//

struct Node nodes[10] = {0};
nodes[5].parent = nodes[0];
nodes[0].someChild = calloc( 1, sizeof(struct Node) );
nodes[5].anotherLink = nodes[3];
for( size_t i = 3; i < 7; i++ ) {
    nodes[i].anotherLink = calloc( 1, sizeof(struct Node) );
}

ที่รันไทม์Nodeกราฟวัตถุทั้งหมดจะกระจัดกระจายรอบพื้นที่หน่วยความจำและโหนดเดียวกันสามารถชี้ไปที่จากโหนดที่แตกต่างกันจำนวนมาก

คุณไม่สามารถถ่ายโอนหน่วยความจำไปยังไฟล์ / สตรีม / ดิสก์และเรียกว่าเป็นอนุกรมเนื่องจากค่าตัวชี้ (ซึ่งเป็นที่อยู่หน่วยความจำ) ไม่สามารถยกเลิกการทำให้เป็นอนุกรม (เนื่องจากตำแหน่งหน่วยความจำเหล่านั้นอาจถูกครอบครองอยู่แล้ว ในหน่วยความจำ) ปัญหาอีกอย่างหนึ่งเกี่ยวกับการทิ้งหน่วยความจำก็คือคุณจะต้องเก็บข้อมูลที่ไม่เกี่ยวข้องทุกประเภทและพื้นที่ที่ไม่ได้ใช้ - ในกระบวนการ x86 กระบวนการมีหน่วยความจำ 4GiB มากถึง 4GiB และ OS หรือ MMU มีแนวคิดทั่วไปว่าหน่วยความจำคืออะไร มีความหมายหรือไม่ (ขึ้นอยู่กับหน้าหน่วยความจำที่กำหนดให้กับกระบวนการ) ดังนั้นการNotepad.exeถ่ายโอนข้อมูลไบต์ดิบ 4GB ลงในดิสก์ของฉันเมื่อใดก็ตามที่ฉันต้องการบันทึกไฟล์ข้อความดูเหมือนจะสิ้นเปลืองเล็กน้อย

ปัญหาอีกประการหนึ่งคือการกำหนดเวอร์ชัน: จะเกิดอะไรขึ้นถ้าคุณทำให้Nodeกราฟเป็นอนุกรมในวันที่ 1 จากนั้นในวันที่ 2 คุณจะเพิ่มฟิลด์อื่นลงไปNode(เช่นค่าตัวชี้อื่นหรือค่าดั้งเดิม) จากนั้นในวันที่ 3 วันที่ 1?

คุณต้องพิจารณาสิ่งอื่น ๆ เช่นความรัก หนึ่งในสาเหตุหลักที่ทำให้ไฟล์ MacOS และ IBM / Windows / PC ไม่สามารถทำงานร่วมกันได้ในช่วงปี 1980 และ 1990 ทั้งๆที่ถูกสร้างขึ้นโดยโปรแกรมเดียวกัน (Word, Photoshop และอื่น ๆ ) เป็นเพราะค่า x86 / PC จำนวนเต็มหลายไบต์ ถูกบันทึกไว้ในลำดับเล็ก ๆ น้อย ๆ แต่คำสั่งซื้อขนาดใหญ่ใน Mac - และซอฟต์แวร์ไม่ได้ถูกสร้างขึ้นโดยคำนึงถึงการพกพาข้ามแพลตฟอร์ม ทุกวันนี้ทุกอย่างดีขึ้นด้วยการพัฒนาการศึกษาของนักพัฒนาและโลกคอมพิวเตอร์ที่แตกต่างกันมากขึ้นเรื่อย ๆ


2
การทิ้งทุกอย่างในพื้นที่หน่วยความจำของกระบวนการจะน่ากลัวด้วยเหตุผลด้านความปลอดภัย คืนของโปรแกรมมีอยู่ในหน่วยความจำทั้ง 1) ข้อมูลสาธารณะบางส่วนและ 2) รหัสผ่าน, nonce ลับหรือคีย์ส่วนตัว เมื่อซีเรียลไลซ์เซกชั่นก่อนหน้านี้จะไม่ต้องการเปิดเผยข้อมูลใด ๆ
Chi

8
บันทึกที่น่าสนใจมากในหัวข้อนี้: เหตุใดรูปแบบไฟล์ Microsoft Office จึงซับซ้อนมาก
โดดเด่น

15

หากินนั้นมีการอธิบายไว้ในคำว่า: " serial ization"

คำถามคือโดยทั่วไป: ฉันจะแสดงกราฟที่กำกับโดยรอบที่ซับซ้อนซึ่งเชื่อมโยงโดยพลการของวัตถุที่ซับซ้อนตามอำเภอใจนั้นเป็นลำดับเชิงเส้นของไบต์ได้อย่างไร

ลองคิดดู: ลำดับเชิงเส้นเป็นชนิดของกราฟที่กำกับโดยความเสื่อมซึ่งทุกจุดยอดมีขอบขาเข้าและขาออกหนึ่งอัน (ยกเว้น "จุดยอดแรก" ซึ่งไม่มีขอบเข้ามาและ "จุดสุดสุดท้าย" ซึ่งไม่มีขอบขาออก) . และไบต์จะเห็นได้ชัดที่ซับซ้อนน้อยกว่าวัตถุ

ดังนั้นดูเหมือนว่าสมเหตุสมผลเมื่อเราไปจากกราฟที่ซับซ้อนโดยพลการไปจนถึง "กราฟ" ที่ จำกัด มากขึ้น (อันที่จริงเป็นเพียงรายการ) และจากวัตถุที่ซับซ้อนตามอำเภอใจจนถึงไบต์ง่าย ๆ ข้อมูลจะหายไปถ้าเราทำอย่างไร้เดียงสา ไม่เข้ารหัสข้อมูล "ภายนอก" อย่างใด และนั่นคือสิ่งที่ทำให้เป็นอนุกรม: เข้ารหัสข้อมูลที่ซับซ้อนในรูปแบบเชิงเส้นง่าย ๆ

หากคุณคุ้นเคยกับYAMLคุณอาจดูที่คุณลักษณะanchorและaliasซึ่งอนุญาตให้คุณแสดงแนวคิดที่ว่า "วัตถุเดียวกันอาจปรากฏในที่ต่าง ๆ " ในการทำให้เป็นอนุกรม

เช่นถ้าคุณมีกราฟต่อไปนี้:

A → B → D
↓       ↑
C ––––––+

คุณสามารถแสดงว่าเป็นรายการของเส้นทางเชิงเส้นใน YAML เช่นนี้:

- [&A A, B, &D D]
- [*A, C, *D]

คุณสามารถแทนมันเป็นรายการ adjacency หรือเมทริกซ์ adjacency หรือเป็นคู่ที่องค์ประกอบแรกคือชุดของโหนดและองค์ประกอบที่สองคือชุดของคู่ของโหนด แต่ในการเป็นตัวแทนเหล่านั้นทั้งหมดคุณต้องมี วิธีการอ้างถึงย้อนกลับและส่งต่อไปยังโหนดที่มีอยู่เช่นตัวชี้ซึ่งโดยทั่วไปคุณไม่มีในไฟล์หรือสตรีมเครือข่าย สิ่งที่คุณมีในท้ายที่สุดคือไบต์

(ซึ่ง BTW หมายความว่าไฟล์ข้อความ YAML ข้างต้นนั้นต้องมี "ซีเรียลไลซ์" ด้วยนั่นคือสิ่งที่การเข้ารหัสตัวอักษรและรูปแบบการถ่ายโอน Unicode ต่าง ๆ สำหรับ ... มันไม่ได้เป็น "อนุกรม" อย่างเข้มงวดเพียงแค่เข้ารหัสเพราะไฟล์ข้อความนั้นเป็นอนุกรม / รายการเชิงเส้นของ codepoints แต่คุณสามารถเห็นความคล้ายคลึงกัน)


13

คำตอบอื่น ๆ ที่อยู่กราฟวัตถุที่ซับซ้อนอยู่แล้ว แต่มันก็คุ้มค่าที่จะชี้ให้เห็นว่าการทำซีเรียลไลซ์เซชั่นแบบอนุกรมนั้นไม่สำคัญ

การใช้ชื่อชนิดดั้งเดิม C สำหรับความเป็นระเบียบพิจารณา:

  1. longฉันเป็นอันดับ บางครั้งฉันยกเลิกการทำให้เป็นอนุกรม แต่ ... บนแพลตฟอร์มที่แตกต่างกันและตอนนี้longเป็นint64_tมากกว่าที่int32_tฉันเก็บไว้ ดังนั้นฉันต้องระวังอย่างมากเกี่ยวกับขนาดที่แน่นอนของทุกประเภทที่ฉันจัดเก็บหรือเก็บข้อมูลเมตาที่อธิบายประเภทและขนาดของทุกฟิลด์

    โปรดทราบว่าแพลตฟอร์มที่แตกต่างนี้อาจเป็นแพลตฟอร์มเดียวกันหลังจากการคอมไพล์ใหม่ในอนาคต

  2. ฉันเป็นอันดับ int32_tบางครั้งฉันยกเลิกการทำให้เป็นอันดับ แต่ในแพลตฟอร์มอื่นและตอนนี้ค่าเสียหาย น่าเศร้าที่ฉันบันทึกค่าไว้บนแพลตฟอร์มใหญ่และโหลดลงบนแพลตฟอร์มเล็ก ๆ ตอนนี้ฉันต้องสร้างแบบแผนสำหรับรูปแบบของฉันหรือเพิ่มข้อมูลเมตาเพิ่มเติมที่อธิบายความ endiannness ของแต่ละไฟล์ / สตรีม / อะไรก็ตาม และแน่นอนว่าควรทำการแปลงที่เหมาะสม

  3. ฉันทำให้เป็นสตริง เวลานี้หนึ่งแพลตฟอร์มใช้charและ UTF-8 และหนึ่งwchar_tและ UTF-16

ดังนั้นฉันจึงอ้างว่าการทำให้เป็นอันดับคุณภาพที่สมเหตุสมผลนั้นไม่ได้สำคัญแม้แต่กับระบบดั้งเดิมในหน่วยความจำต่อเนื่อง มีการตัดสินใจเข้ารหัสมากมายที่คุณต้องใช้กับเอกสารหรืออธิบายด้วยข้อมูลเมตาแบบอินไลน์

กราฟวัตถุจะเพิ่มความซับซ้อนอีกชั้นหนึ่ง


6

มีหลายแง่มุม:

การอ่านโดยโปรแกรมเดียวกัน

โปรแกรมของคุณจัดเก็บข้อมูลของคุณเป็นไบต์ในหน่วยความจำ แต่มันอาจกระจัดกระจายไปตามรีจิสเตอร์ที่แตกต่างกันโดยมีพอยน์เตอร์จะกลับไปกลับมาระหว่างชิ้นเล็ก ๆ ของมัน [แก้ไข: ตามที่แสดงความคิดเห็นทางกายภาพข้อมูลมีแนวโน้มที่จะอยู่ในหน่วยความจำหลักมากกว่าการลงทะเบียนข้อมูล . แค่คิดว่ารายการจำนวนเต็มเชื่อมโยง องค์ประกอบรายการแต่ละรายการอาจถูกเก็บไว้ในสถานที่ที่แตกต่างกันโดยสิ้นเชิงและองค์ประกอบทั้งหมดที่มีรายการด้วยกันคือตัวชี้จากองค์ประกอบหนึ่งไปยังอีกองค์ประกอบหนึ่ง หากคุณต้องนำข้อมูลดังกล่าวมาใช้และพยายามที่จะคัดลอกไปยังเครื่องอื่นที่รันโปรแกรมเดียวกันคุณจะพบปัญหา:

  1. ก่อนอื่นการลงทะเบียนที่อยู่ข้อมูลของคุณจะถูกเก็บไว้ในเครื่องหนึ่งอาจใช้สิ่งที่แตกต่างไปจากเครื่องอื่นอย่างสิ้นเชิง (บางคนกำลังเรียกดูการแลกเปลี่ยนสแต็ก ดังนั้นถ้าคุณเพียงแค่แทนที่การลงทะเบียนเบราว์เซอร์ลาก่อน ดังนั้นคุณจะต้องจัดเรียงพอยน์เตอร์ในโครงสร้างอีกครั้งเพื่อให้พอดีกับที่อยู่ที่คุณว่างบนเครื่องที่สอง ปัญหาเดียวกันนี้เกิดขึ้นเมื่อคุณพยายามโหลดข้อมูลบนเครื่องเดียวกันอีกครั้งในภายหลัง
  2. ถ้าส่วนประกอบภายนอกบางจุดในโครงสร้างของคุณหรือโครงสร้างของคุณมีพอยน์เตอร์ไปยังข้อมูลภายนอกคุณไม่ได้ส่งข้อมูล Segfaults ทุกที่! นี่จะกลายเป็นฝันร้ายในการดีบัก

การอ่านโดยโปรแกรมอื่น

สมมติว่าคุณจัดการจัดสรรที่อยู่ที่ถูกต้องในเครื่องอื่นเพื่อให้ข้อมูลของคุณเหมาะสม หากข้อมูลของคุณถูกประมวลผลโดยโปรแกรมแยกต่างหากในเครื่องนั้น (ภาษาที่แตกต่างกัน) โปรแกรมนั้นอาจมีความเข้าใจพื้นฐานของข้อมูลที่แตกต่างกันโดยสิ้นเชิง สมมติว่าคุณมีออบเจ็กต์ C ++ พร้อมพอยน์เตอร์ แต่ภาษาเป้าหมายของคุณไม่สนับสนุนพอยน์เตอร์ในระดับนั้น อีกครั้งคุณท้ายไม่มีวิธีที่สะอาดเพื่อที่อยู่ข้อมูลนั้นในโปรแกรมที่สอง คุณจบลงด้วยข้อมูลไบนารี่บางส่วนในหน่วยความจำ แต่จากนั้นคุณต้องเขียนโค้ดพิเศษที่ล้อมรอบข้อมูลและแปลมันเป็นสิ่งที่ภาษาเป้าหมายของคุณสามารถทำงานได้ ดูเหมือนว่าการดีซีเรียลไลเซชันเพียงแค่ตอนนี้จุดเริ่มต้นของคุณคือวัตถุแปลก ๆ กระจัดกระจายอยู่รอบ ๆ หน่วยความจำหลักของคุณซึ่งแตกต่างกันไปตามภาษาต้นฉบับ แทนไฟล์ที่มีโครงสร้างที่กำหนดไว้อย่างดี แน่นอนเช่นเดียวกันหากคุณพยายามตีความไฟล์ไบนารีที่มีพอยน์เตอร์โดยตรงคุณต้องเขียนโปรแกรมแยกวิเคราะห์สำหรับทุกวิถีทางที่เป็นไปได้ที่ภาษาอื่นอาจใช้แทนข้อมูลในหน่วยความจำ

การอ่านโดยมนุษย์

ภาษาซีเรียลไลเซชั่นที่ทันสมัยที่สุดสองภาษาสำหรับการทำให้เป็นอนุกรมบนเว็บ (xml, json) สามารถเข้าใจได้ง่ายโดยมนุษย์ แทนที่จะเป็นเลขฐานสองของสารที่หนาโครงสร้างที่แท้จริงและเนื้อหาของข้อมูลจะชัดเจนแม้ว่าจะไม่มีโปรแกรมให้อ่านข้อมูลก็ตาม สิ่งนี้มีข้อดีหลายประการ:

  • การดีบักง่ายขึ้น -> หากมีปัญหาในบริการไปป์ไลน์คุณเพียงแค่ดูข้อมูลที่มาจากบริการเดียวและตรวจสอบว่าเหมาะสมหรือไม่ (เป็นขั้นตอนแรก); คุณยังดูโดยตรงว่าข้อมูลดูเหมือนว่าคุณคิดว่าควรเมื่อคุณเขียนอินเตอร์เฟซการส่งออกของคุณในสถานที่แรก
  • การเก็บถาวร: ถ้าคุณมีข้อมูลของคุณในรูปแบบไบนารีสารที่หนาแบบไบนารีและคุณปล่อยโปรแกรมที่มีความหมายในการตีความคุณจะสูญเสียข้อมูล (หรือคุณจะต้องใช้เวลาพอสมควรในการหาบางสิ่งในนั้น); หากข้อมูลที่ต่อเนื่องของคุณเป็นแบบอ่านได้คุณสามารถใช้มันเป็นไฟล์เก็บถาวรหรือโปรแกรมผู้นำเข้าของคุณเองสำหรับโปรแกรมใหม่
  • ลักษณะการเปิดเผยข้อมูลของข้อมูลในลักษณะนี้ยังหมายถึงว่าเป็นอิสระจากระบบคอมพิวเตอร์และฮาร์ดแวร์ คุณสามารถโหลดมันลงในคอมพิวเตอร์ควอนตัมที่สร้างขึ้นแตกต่างกันโดยสิ้นเชิงหรือติดเชื้อเอไอมนุษย์ต่างดาวที่มีข้อมูลทางเลือกอื่น ๆ ดังนั้นมันจึงบินไปยังดวงอาทิตย์ถัดไปโดยไม่ตั้งใจ (Emmerich ถ้าคุณอ่านบทความนี้ ภาพยนตร์)

ข้อมูลของฉันอาจเป็นส่วนใหญ่ในหน่วยความจำหลักไม่ใช่ในการลงทะเบียน หากข้อมูลของฉันเหมาะกับการลงทะเบียนการทำให้เป็นอันดับเป็นสิ่งที่แทบจะไม่มีปัญหาเลย ฉันคิดว่าคุณเข้าใจผิดว่าการลงทะเบียนคืออะไร
David Richerby

อันที่จริงฉันใช้คำว่า register ที่นี่มากเกินไป แต่ประเด็นหลักคือข้อมูลของคุณอาจมีตัวชี้ไปยังพื้นที่ที่อยู่เพื่อระบุองค์ประกอบของตัวเองหรือเพื่ออ้างถึงข้อมูลอื่น ๆ มันไม่สำคัญว่าจะเป็นการลงทะเบียนทางกายภาพหรือที่อยู่เสมือนในหน่วยความจำหลัก
Frank Hopkins

ไม่คุณใช้คำว่า "register" ไม่ถูกต้องอย่างสมบูรณ์ สิ่งที่คุณกำลังเรียกใช้รีจิสเตอร์นั้นอยู่ในส่วนต่าง ๆ ของลำดับชั้นหน่วยความจำถึงรีจิสเตอร์จริง
David Richerby

6

นอกจากคำตอบอื่น ๆ ที่ได้กล่าวไปแล้ว:

บางครั้งคุณต้องการเรียงลำดับสิ่งที่ไม่ใช่ข้อมูลที่บริสุทธิ์

ตัวอย่างเช่นคิดถึงการจัดการไฟล์หรือการเชื่อมต่อกับเซิร์ฟเวอร์ แม้ว่าตัวจัดการไฟล์หรือซ็อกเก็ตจะเป็นintตัวเลขนี้ก็ไม่มีความหมายในครั้งถัดไปที่โปรแกรมทำงาน ในการสร้างวัตถุที่มีการจัดการกับสิ่งต่าง ๆ อย่างเหมาะสมคุณจะต้องเปิดไฟล์และสร้างการเชื่อมต่อใหม่อีกครั้งและตัดสินใจว่าจะทำอย่างไรถ้าสิ่งนี้ล้มเหลว

หลายภาษาในทุกวันนี้สนับสนุนการจัดเก็บฟังก์ชันที่ไม่ระบุชื่อภายในวัตถุเช่นonBlah()ตัวจัดการใน Javascript สิ่งนี้เป็นสิ่งที่ท้าทายเนื่องจากรหัสดังกล่าวสามารถมีการอ้างอิงไปยังข้อมูลเพิ่มเติมซึ่งจำเป็นต้องถูกทำให้เป็นอนุกรม (และจากนั้นก็มีปัญหาของรหัสซีเรียลไลซ์เซชั่นในทางข้ามแพลตฟอร์มซึ่งเห็นได้ชัดว่าง่ายต่อการตีความภาษา) แม้ถึงแม้จะรองรับเพียงบางส่วนของภาษา แต่ก็ยังสามารถพิสูจน์ได้ว่ามีประโยชน์มาก ไม่อนุกรมของกลไกหลายพยายามที่จะการจัดเรียงรหัส แต่เห็นเป็นอันดับ-จาวาสคริปต์

ในกรณีที่คุณต้องการทำให้เป็นอันดับวัตถุ แต่มันมีบางสิ่งที่ไม่ได้รับการสนับสนุนโดยกลไกการทำให้เป็นอันดับของคุณคุณต้องเขียนรหัสใหม่ในลักษณะที่ใช้งานได้ ตัวอย่างเช่นคุณสามารถใช้ enums แทนฟังก์ชั่นที่ไม่ระบุชื่อเมื่อมีจำนวนฟังก์ชันที่เป็นไปได้ จำกัด

บ่อยครั้งที่คุณต้องการให้ข้อมูลเรียงลำดับแบบสั้น ๆ

หากคุณกำลังส่งข้อมูลผ่านเครือข่ายหรือจัดเก็บไว้ในดิสก์อาจเป็นเรื่องสำคัญที่จะต้องรักษาขนาดให้เล็ก วิธีที่ง่ายที่สุดวิธีหนึ่งในการบรรลุเป้าหมายนี้คือการทิ้งข้อมูลที่สามารถสร้างใหม่ได้ (ตัวอย่างเช่นการทิ้งแคชแคชตารางแฮชและการเป็นตัวแทนสำรองของข้อมูลเดียวกัน)

แน่นอนโปรแกรมเมอร์ต้องเลือกสิ่งที่จะบันทึกด้วยตนเองและสิ่งที่จะถูกทิ้งและตรวจสอบให้แน่ใจว่าสิ่งที่ถูกสร้างขึ้นมาใหม่เมื่อวัตถุถูกสร้างขึ้นใหม่

คิดเกี่ยวกับการกระทำของการบันทึกเกม วัตถุอาจมีพอยน์เตอร์จำนวนมากสำหรับข้อมูลกราฟิกข้อมูลเสียงและวัตถุอื่น ๆ แต่สิ่งเหล่านี้ส่วนใหญ่สามารถโหลดได้จากไฟล์ข้อมูลเกมและไม่จำเป็นต้องเก็บไว้ในไฟล์บันทึก การละทิ้งมันอาจเป็นเรื่องลำบากดังนั้นสิ่งเล็ก ๆ น้อย ๆ มักจะถูกทิ้งไว้ฉันแก้ไขไฟล์บันทึกบางไฟล์ในเวลาของฉันและค้นพบข้อมูลที่ซ้ำซ้อนอย่างชัดเจนเช่นคำอธิบายรายการที่เป็นข้อความ

บางครั้งพื้นที่ไม่สำคัญ แต่ความสามารถในการอ่านคือ - ในกรณีนี้คุณอาจใช้รูปแบบ ASCII (อาจเป็น JSON หรือ XML) แทน


3

ลองกำหนดว่าจริง ๆ แล้วลำดับของไบต์คืออะไร ลำดับของไบต์ประกอบด้วยจำนวนเต็มไม่เป็นลบเรียกว่ายาวและบางฟังก์ชั่นโดยพล / จดหมายที่แมจำนวนเต็มใด ๆฉันที่มีอย่างน้อยศูนย์และน้อยกว่าความยาวถึงค่าไบต์ (จำนวนเต็ม 0-255)

วัตถุจำนวนมากที่คุณจัดการด้วยในโปรแกรมทั่วไปไม่ได้อยู่ในรูปแบบนั้นเพราะวัตถุนั้นประกอบไปด้วยการจัดสรรหน่วยความจำที่แตกต่างกันจำนวนมากซึ่งอยู่ในสถานที่ต่าง ๆ ใน RAM และสามารถแยกออกจากกันได้โดยหลายล้านไบต์ ไม่สนใจ แค่คิดถึงรายการเชื่อมโยงพื้นฐาน: แต่ละโหนดในรายการคือลำดับของไบต์ใช่ แต่โหนดอยู่ในตำแหน่งต่าง ๆ มากมายในหน่วยความจำของคอมพิวเตอร์ของคุณและเชื่อมต่อกับพอยน์เตอร์ หรือลองนึกถึงโครงสร้างอย่างง่ายที่มีตัวชี้ไปยังสตริงที่มีความยาวผันแปรได้

เหตุผลที่เราต้องการทำให้โครงสร้างข้อมูลเป็นอนุกรมในลำดับไบต์มักจะเป็นเพราะเราต้องการเก็บไว้ในดิสก์หรือส่งไปยังระบบอื่น (เช่นผ่านเครือข่าย) หากคุณพยายามเก็บตัวชี้ไว้บนดิสก์หรือส่งไปยังระบบอื่นมันจะไร้ประโยชน์เพราะโปรแกรมที่อ่านตัวชี้นั้นจะมีชุดของพื้นที่หน่วยความจำที่แตกต่างกัน


1
ฉันไม่แน่ใจว่าเป็นคำจำกัดความที่ยอดเยี่ยมของลำดับ คนส่วนใหญ่จะกำหนดลำดับที่จะดีลำดับ: บรรทัดของสิ่งหนึ่งหลังจากที่อื่น ตามคำนิยามของคุณint seq(int i) { if (0 <= i < length) return i+1; else return -1;}เป็นลำดับ ดังนั้นฉันจะเก็บที่บนดิสก์ได้อย่างไร
David Richerby

1
หากความยาวเท่ากับ 4 ฉันจะจัดเก็บไฟล์สี่ไบต์พร้อมเนื้อหา: 1, 2, 3, 4
David Grayson

1
@DavidRicherby คำจำกัดความของเขาเทียบเท่ากับ "เส้นของสิ่งหนึ่งต่อกัน" มันเป็นเพียงนิยามทางคณิตศาสตร์และแม่นยำมากกว่านิยามที่ใช้งานง่ายของคุณ โปรดทราบว่าฟังก์ชั่นของคุณไม่ใช่ลำดับเนื่องจากมีลำดับคุณต้องใช้ฟังก์ชันนั้นและจำนวนเต็มอื่นซึ่งเรียกว่าความยาว
user253751

1
จุด @FreshAir ของฉันอยู่ที่ลำดับคือ 1, 2, 3, 4, 5 สิ่งที่ผมเขียนลงเป็นฟังก์ชั่น ฟังก์ชันไม่ใช่ลำดับ
David Richerby

1
วิธีง่ายๆในการเขียนฟังก์ชั่นลงดิสก์คือสิ่งที่ฉันเสนอไปแล้ว: สำหรับทุกอินพุตที่เป็นไปได้ให้เก็บเอาต์พุต ฉันคิดว่าบางทีคุณยังไม่เข้าใจ แต่ฉันไม่แน่ใจว่าจะพูดอะไร คุณรู้หรือไม่ว่าในระบบฝังตัวมันเป็นเรื่องปกติที่จะแปลงฟังก์ชั่นราคาแพงเช่นsinลงในตารางการค้นหาซึ่งเป็นลำดับตัวเลขหรือไม่? คุณทราบหรือไม่ว่าฟังก์ชั่นของคุณเหมือนกับอินพุทที่เราสนใจ int seq(n) { int a[] = [1, 2, 3, 4]; return a[n]; } ทำไมว่าที่คุณพูดว่าไฟล์สี่ไบต์ของฉันคือการแสดงที่ไม่เพียงพอ?
David Grayson

2

ความสลับซับซ้อนสะท้อนถึงความซับซ้อนของข้อมูลและวัตถุเอง วัตถุเหล่านี้อาจเป็นวัตถุในโลกแห่งความจริงหรือวัตถุคอมพิวเตอร์เท่านั้น คำตอบอยู่ในชื่อ การทำให้เป็นอนุกรมเป็นตัวแทนเชิงเส้นของวัตถุหลายมิติ มีปัญหามากมายนอกเหนือจาก RAM ที่แยกส่วน

หากคุณสามารถเรียบ 12 อาร์เรย์ห้ามิติและรหัสโปรแกรมบางส่วนการทำให้เป็นอนุกรมยังช่วยให้คุณถ่ายโอนโปรแกรมคอมพิวเตอร์ทั้งหมด (และข้อมูล) ระหว่างเครื่อง โปรโตคอลการคำนวณแบบกระจายเช่น RMI / CORBA ใช้การทำให้เป็นอนุกรมอย่างกว้างขวางเพื่อถ่ายโอนข้อมูลและโปรแกรม

พิจารณาค่าโทรศัพท์ของคุณ อาจเป็นวัตถุชิ้นเดียวซึ่งประกอบด้วยการโทรทั้งหมดของคุณ (รายการสตริง) จำนวนเงินที่ต้องชำระ (จำนวนเต็ม) และประเทศ หรือค่าโทรศัพท์ของคุณอาจอยู่ข้างในจากด้านบนและประกอบด้วยการโทรแยกรายการที่เชื่อมโยงกับชื่อของคุณ แต่ละแบนจะดูแตกต่างสะท้อนให้เห็นถึงวิธีที่ บริษัท โทรศัพท์ของคุณเขียนซอฟต์แวร์รุ่นนั้นและเหตุผลที่ฐานข้อมูลเชิงวัตถุไม่เคยถอดออก

บางส่วนของโครงสร้างอาจไม่อยู่ในหน่วยความจำเลย หากคุณมีการแคชขี้เกียจบางส่วนของวัตถุอาจถูกอ้างอิงถึงไฟล์ดิสก์เท่านั้นและจะถูกโหลดเมื่อเข้าถึงส่วนนั้นของวัตถุนั้นเท่านั้น นี่เป็นเรื่องธรรมดาในกรอบการคงอยู่ที่ร้ายแรง BLOBs เป็นตัวอย่างที่ดี เก็ตตี้อิมเมจอาจเก็บรูปภาพขนาดใหญ่หลายเมกะไบต์ของ Fidel Castro และข้อมูลเมตาบางอย่างเช่นชื่อของรูปภาพค่าเช่าและรูปภาพเอง คุณอาจไม่ต้องการโหลดภาพ 200 MB ลงในหน่วยความจำทุกครั้งเว้นแต่ว่าคุณจะมองเขา ต่อเนื่องไฟล์ทั้งหมดจะต้องมีพื้นที่จัดเก็บมากกว่า 200MB

วัตถุบางอย่างไม่สามารถทำให้เป็นอนุกรมได้เลย ในพื้นที่ของการเขียนโปรแกรม Java คุณสามารถมีวัตถุการเขียนโปรแกรมแสดงหน้าจอกราฟิกหรือพอร์ตอนุกรมทางกายภาพ ไม่มีแนวคิดที่แท้จริงของการทำให้เป็นอันดับอย่างใดอย่างหนึ่ง คุณจะส่งพอร์ตไปยังบุคคลอื่นผ่านเครือข่ายได้อย่างไร

บางสิ่งเช่นรหัสผ่าน / คีย์เข้ารหัสไม่ควรจัดเก็บหรือส่งผ่าน พวกเขาสามารถติดแท็กเช่น (ระเหย / ชั่วคราว ฯลฯ ) และกระบวนการทำให้เป็นอนุกรมจะข้ามพวกเขา แต่พวกเขาสามารถอยู่ในแรม การข้ามแท็กเหล่านี้คือวิธีที่คีย์การเข้ารหัสได้รับส่ง / เก็บโดยไม่ตั้งใจใน ASCII ธรรมดา

นี่และคำตอบอื่น ๆ คือเหตุผลว่าทำไมมันซับซ้อน


2

ปัญหาที่ฉันมีคือ: ไม่ใช่ตัวแปรทั้งหมด (ไม่ว่าจะเป็นแบบดั้งเดิมเช่นวัตถุ int หรือคอมโพสิต) ที่แสดงด้วยลำดับไบต์แล้ว

ใช่พวกเขาเป็น ปัญหานี่คือรูปแบบของไบต์เหล่านั้น ง่าย ๆintสามารถมีความยาว 2, 4 หรือ 8 บิต มันอาจเป็นในขนาดเล็กหรือใหญ่ endian มันสามารถไม่ได้ลงนามเซ็นชื่อด้วยส่วนเสริม 1 หรือแม้กระทั่งในการเข้ารหัสบิตที่แปลกใหม่บางอย่างเช่น negabinary

หากคุณเพิ่งถ่ายโอนข้อมูลintจากหน่วยความจำแบบไบนารีและเรียกมันว่า "ซีเรียลไลซ์" คุณต้องแนบคอมพิวเตอร์ทั้งระบบปฏิบัติการและโปรแกรมของคุณเพื่อให้สามารถกำจัดได้ หรืออย่างน้อยคำอธิบายที่แม่นยำของพวกเขา

ดังนั้นสิ่งที่ทำให้เป็นอันดับเช่นหัวข้อลึก ในการทำให้เป็นอนุกรมตัวแปรเราไม่สามารถนำไบต์เหล่านี้ในหน่วยความจำแล้วเขียนมันไปยังไฟล์ได้หรือไม่? ฉันพลาดอะไรไปบ้าง?

การทำให้เป็นอันดับของวัตถุอย่างง่ายนั้นค่อนข้างจะเขียนลงไปตามกฎบางอย่าง กฎเหล่านั้นมีมากมายและไม่ชัดเจนเสมอไป เช่นxs:integerใน XML ถูกเขียนในฐาน -10 ไม่ใช่ฐาน -16 ไม่ใช่ฐาน -9 แต่ 10 ไม่ใช่ข้อสมมติที่ซ่อนอยู่เป็นกฎจริง และกฎดังกล่าวทำให้การเป็นอันดับเป็นอนุกรม เพราะสวยมากมีกฎระเบียบที่เกี่ยวกับรูปแบบบิตของโปรแกรมของคุณในหน่วยความจำ

นั่นเป็นเพียงส่วนหนึ่งของภูเขาน้ำแข็ง ลองมาตัวอย่างลำดับของวิทยาการที่ง่ายผู้ที่ใช้งาน: structซี คุณอาจคิดอย่างนั้น

struct {
short width;
short height;
long count;
}

มีรูปแบบหน่วยความจำที่กำหนดไว้ในคอมพิวเตอร์ + OS ที่กำหนดหรือไม่ ก็ไม่ได้ #pragma packคอมไพเลอร์จะแพดฟิลด์ขึ้นอยู่กับการตั้งค่าปัจจุบัน ในการตั้งค่าเริ่มต้นของการคอมไพล์ 32 บิตทั้งสองshortsจะถูกเพิ่มเป็น 4 ไบต์ดังนั้นstructจริง ๆ แล้วจะมี 3 ฟิลด์ 4 ไบต์ในหน่วยความจำ ดังนั้นตอนนี้คุณไม่เพียงแค่ต้องระบุว่าshortมีความยาว 16 บิตมันเป็นจำนวนเต็มเขียนในส่วนเติมเต็มลบ 1, ใหญ่หรือน้อย endian คุณต้องจดบันทึกการตั้งค่าการจัดโครงสร้างของโปรแกรมที่คอมไพล์ด้วย

นั่นเป็นสิ่งที่ค่อนข้างเกี่ยวกับการจัดลำดับ: การสร้างชุดของกฎและยึดติดกับพวกเขา

กฎเหล่านั้นสามารถขยายได้แล้วที่จะยอมรับแม้โครงสร้างที่ซับซ้อนมากขึ้น (เช่นรายการตัวแปรความยาวหรือข้อมูลไม่เป็นเชิงเส้น) คุณสมบัติเพิ่มเช่นการอ่านของมนุษย์เวอร์ชันที่เข้ากันได้ย้อนหลังและการแก้ไขข้อผิดพลาดอื่น ๆ แต่ถึงแม้จะเขียนลงเป็นหนึ่งเดียวintมีความซับซ้อนมากพอถ้าคุณ เพียงต้องการให้แน่ใจว่าคุณจะสามารถอ่านได้อย่างน่าเชื่อถือ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.