Reputation: 43
I'm completely new to programming. This is my first 'proper' project that will be used by other people.
The program asks various questions then writes a new shop entry to a file. With a empty file I have most of it working, but the finished product needs to insert the entries at a specific point within an existing file.
2 issues have me baffled:
How do I insert new shop entries into the file before 'Back:' and how do i increment 'InventoryLocation:' by 1 each time an entry is added
the file being appended to has this structure:
# shop 1
SuperSpaceSquids:
RewardType: playercommand
PriceType: free
Reward:
- ewarp Shop-SuperSpaceSquids
MenuItem:
- type:SKULL_ITEM
- playerhead:MHF_Squid
- durability:3
- amount:1
- name:&5SuperSpaceSquids
- 'lore:&6&o"Squid Shop From Space!"'
Message: ''
InventoryLocation: 38
ExtraPermission: ''
# shop 2
HadesKitty:
RewardType: playercommand
PriceType: free
Reward:
- ewarp Shop-HadesKitty
MenuItem:
- type:SKULL_ITEM
- playerhead:Turtle_Em
- durability:3
- amount:1
- name:&5HadesKitty
- 'lore:&6&o"our prices are fair!..."'
Message: ''
InventoryLocation: 39 # This value needs to be incremented by 1 each time
ExtraPermission: ''
>> insert new shops here <<
Back:
RewardType: shop
PriceType: free
Reward: Shop_Menu
MenuItem:
- type:REDSTONE
- amount:1
- name:&cBack
- lore:&8Back to Shop Menu
InventoryLocation: 54
This is the fuction that writes to the file:
def write(shop, id, data, desc, skull):
f = open('file.yml', 'w')
f.write(" %s:" % shop)
f.write("\n RewardType: playercommand")
f.write("\n PriceType: free")
f.write("\n Reward:")
f.write("\n - ewarp shop-%s" % shop)
f.write("\n MenuItem:")
if skull:
f.write("\n - Type:SKULL_ITEM")
f.write("\n - playerhead:%s" % skull)
f.write("\n - durability:3")
if not skull:
f.write("\n - id:%s" % id)
if data:
f.write("\n - durability:%s" % data)
f.write("\n - amount:1")
f.write("\n - name:&5%s" % shop)
f.write("\n - 'lore:&6&o\"%s\"'" % desc)
f.write("\n Message:")
f.write("\n InventoryLocation:")
f.write("\n ExtraPermission: ''")
f.flush()
print "\nAll done."
print "\nHit Return to quit or 1 to add more shops."
while True:
choice = raw_input(prompt)
if choice == "":
print "\nGoodbye!"
f.close()
time.sleep(2)
exit(0)
elif choice == "1":
os.system('cls' if os.name == 'nt' else 'clear')
input()
else:
print "I dont understand that."
Upvotes: 4
Views: 239
Reputation: 41
As far as I know, we could not modify the middle of a file.
You just have 2 choices:
read all the file to the memory as a list, then modify the list, then write all the list to the file.
(recommended) use an xml file to save the information but not a normal file. Thus you can use a lot of tools to write or read it.
Upvotes: -1
Reputation: 1933
This is an interesting question and heinst provided a great solution. I have some reservations about the architecture though. Here are the issues I see, which can be ignored if this is a very small project and expected to be used for a limited time.
Concurrency and parallelism issues: If multiple users simultaneously try to read and update the inventory, we need a different solution. Instead of filesystem as persistent store, a database can easily support multiple simultaneous transactions on inventory.
Scalability issues: As the transactions add up with time, the file size grows and reading the whole file and updating it will not scale well. The transactions will have to be split between multiple files using some scheme.
Upvotes: 1
Reputation: 8786
This is a great question. I wrote two functions for you:
insert_before_back(list, list)
insert_before_back
takes in a list of the lines of the file and a list of all the lines you want to add before Back:
, then this returns a list, with the items added in the correct index.
add_inventory(list, string)
add_inventory
takes in a list of the lines of the file and the shop name whose inventory you wish to increment. It then goes through and increments that number by one and resets the value in the list to the newly incremented value. It the returns a list of the new lines.
You can use these to modify the list of the lines you read in, and then just go through all the newly modified items in the list and write each item to the file with the same name.
Heres an example of me using the two functions:
def insert_before_back(lines, thingsToAdd):
backIndex = lines.index('Back:\n')
for item in reversed(thingsToAdd):
lines.insert(backIndex, item)
return lines
def add_inventory(lines, shopName):
shopFound = 0
for i in range(len(lines)):
if shopName in lines[i]:
shopFound = 1
if 'InventoryLocation:' in lines[i] and shopFound:
shopFound = 0
lineSplit = lines[i].split(': ')
incrementInventory = str(int(lineSplit[-1]) + 1)
lineSplit[-1] = incrementInventory + '\n'
lines[i] = ': '.join(lineSplit)
newLines = []
with open('input.txt', 'r') as f:
inputLines = f.readlines()
newLines = insert_before_back(inputLines, ['Hello\n', 'From\n', 'heinst\n'])
add_inventory(newLines, 'HadesKitty')
with open('output.txt', 'w') as f:
for line in newLines:
f.write(line)
Upvotes: 1